package com.sztx.pay.center.core.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.alibaba.dubbo.common.logger.LogMsgNoConverter;
import com.alibaba.fastjson.JSONObject;
import com.berbon.msgsrv.proxy.facade.MsgSrvProxyFacade;
import com.berbon.msgsrv.proxy.pojo.ProxyRequestParam;
import com.sztx.commons.httpclient.HttpClientUtil;
import com.sztx.pay.center.common.util.ConfigUtil;
import com.sztx.pay.center.common.util.Constance;
import com.sztx.pay.center.common.util.Constance.ActLevel;
import com.sztx.pay.center.common.util.Constance.ActState;
import com.sztx.pay.center.common.util.Constance.BindCardStatus;
import com.sztx.pay.center.common.util.Constance.BindCardType;
import com.sztx.pay.center.common.util.Constance.CardActType;
import com.sztx.pay.center.common.util.Constance.CardType;
import com.sztx.pay.center.common.util.Constance.IdCardType;
import com.sztx.pay.center.common.util.Constance.InnerTransferType;
import com.sztx.pay.center.common.util.Constance.PayFlowState;
import com.sztx.pay.center.common.util.Constance.PayFlowType;
import com.sztx.pay.center.common.util.Constance.TradeMessageType;
import com.sztx.pay.center.common.util.Constance.TradeOrderType;
import com.sztx.pay.center.common.util.Constance.UserActType;
import com.sztx.pay.center.common.util.Constance.UserType;
import com.sztx.pay.center.common.util.DateUtil;
import com.sztx.pay.center.common.util.IDCardUtil;
import com.sztx.pay.center.common.util.JFUtils;
import com.sztx.pay.center.common.util.MsgSrvRsp;
import com.sztx.pay.center.common.util.MsgSrvUtil;
import com.sztx.pay.center.common.util.StringUtil;
import com.sztx.pay.center.common.util.ValidateUtil;
import com.sztx.pay.center.common.yhbf.YHBFSensitiveEnc;
import com.sztx.pay.center.common.yhbf.YHBFUtil;
import com.sztx.pay.center.core.service.AccountService;
import com.sztx.pay.center.core.service.ActService;
import com.sztx.pay.center.core.service.BankUtilService;
import com.sztx.pay.center.core.service.BillnoService;
import com.sztx.pay.center.core.service.MqMessageService;
import com.sztx.pay.center.core.service.OrderMappingService;
import com.sztx.pay.center.core.service.PayCoreCallBack;
import com.sztx.pay.center.core.service.PayCoreService;
import com.sztx.pay.center.core.service.UserInfoService;
import com.sztx.pay.center.core.service.bean.BankInfo;
import com.sztx.pay.center.core.service.bean.BindCardMqMsg;
import com.sztx.pay.center.core.service.bean.BindInfo;
import com.sztx.pay.center.core.service.bean.CreateActRep;
import com.sztx.pay.center.core.service.bean.PayCoreAccountInfo;
import com.sztx.pay.center.core.service.bean.PayCoreResult;
import com.sztx.pay.center.core.service.bean.PayCoreTradeInfo;
import com.sztx.pay.center.core.service.bean.PayCoreTransfer;
import com.sztx.pay.center.core.service.bean.PayCoreTransferReq;
import com.sztx.pay.center.core.service.bean.TfBindQuickPay;
import com.sztx.pay.center.core.service.bean.TfBindWithdraw;
import com.sztx.pay.center.core.service.bean.TradeInfo;
import com.sztx.pay.center.core.service.bean.rpc.QueryMerBindCardRequest;
import com.sztx.pay.center.core.service.bean.rpc.ResponsePageModel;
import com.sztx.pay.center.core.service.bean.rpc.TradeFlowMessage;
import com.sztx.pay.center.core.service.bean.rpc.UserActInfoResponse;
import com.sztx.pay.center.core.service.bean.rpc.UserInfoRequest;
import com.sztx.pay.center.core.service.bean.rpc.UserInfoResponse;
import com.sztx.pay.center.core.service.bean.rpc.UserInfoResponse.UserActDetail;
import com.sztx.pay.center.core.service.util.BanksManage;
import com.sztx.pay.center.dataaccess.dao.mysql.GatewaySwiftCodeBankIdMappingMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.OrderB2cMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.OrderRechargeMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.OrderWithdrawMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.UserActFlowMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.UserActFreezeMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.UserActMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.UserBindCardMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.UserInfoMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.redis.LockRedisDAO;
import com.sztx.pay.center.dataaccess.dao.redis.UserRedisDAO;
import com.sztx.pay.center.dataaccess.domain.OrderB2cDO;
import com.sztx.pay.center.dataaccess.domain.UserActAmountDO;
import com.sztx.pay.center.dataaccess.domain.UserActDO;
import com.sztx.pay.center.dataaccess.domain.UserBindCardDO;
import com.sztx.pay.center.dataaccess.domain.UserInfoDO;
import com.sztx.pay.center.dataaccess.domain.UserInfoListDO;
import com.sztx.se.common.exception.BusinessException;
import com.sztx.se.common.util.UUIDUtil;
import com.sztx.se.core.service.impl.BaseServiceImpl;
import com.sztx.se.dataaccess.mysql.config.PageQuery;
import com.sztx.se.rpc.dubbo.client.DubboClientFactory;
import com.sztx.trade.payment.gateway.rpc.api.service.bankutil.BankUtilRpcService;
import com.sztx.trade.payment.gateway.rpc.api.service.bankutil.ReqGetBankCardInfo;
import com.sztx.trade.payment.gateway.rpc.api.service.bankutil.RespGetBankCardInfo;
import com.sztx.trade.payment.gateway.rpc.api.service.bankutil.RespGetBankCardInfo.BankCardInfo;
import com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.BankCardBindingRpcService;
import com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.ReqBindBankCard;
import com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.ReqBindBankCard.BankCard;
import com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.ReqReSendVerifyCode;
import com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.ReqTransferBindOrder;
import com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.ReqVerifyBindBankCard;
import com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.RespBindBankCard;
import com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.RespReSendVerifyCode;
import com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.RespVerifyBindBankCard;
import com.sztx.trade.payment.sztf.common.CommonReqData.RiskParams;
import com.sztx.trade.payment.sztf.service.query.SztfQueryService;
import com.sztx.trade.payment.sztf.service.query.impl.SztfQueryServiceImpl;
import com.sztx.trade.payment.sztf.service.query.model.QueryUserActReqData;
import com.sztx.trade.payment.sztf.service.query.model.QueryUserActRespData;
import com.sztx.trade.payment.sztf.service.user.SztfUserService;
import com.sztx.trade.payment.sztf.service.user.impl.SztfUserServiceImpl;
import com.sztx.trade.payment.sztf.service.user.model.MigrateUserReqData;
import com.sztx.trade.payment.sztf.service.user.model.MigrateUserRespData;
import com.sztx.trade.payment.sztf.service.user.model.RealAuthReqData;
import com.sztx.trade.payment.sztf.service.user.model.RealAuthRespData;
import com.sztx.usercenter.rpc.api.domain.out.UserStatusInfoVO;
import com.sztx.usercenter.rpc.api.domain.out.UserVO;
import com.sztx.usercenter.rpc.api.service.QueryUserInfoService;

@Service
public class AccountServiceImpl extends BaseServiceImpl implements AccountService,PayCoreCallBack{

	@Autowired
	private BillnoService billnoService;
	
	@Autowired
	private PayCoreService payCoreService;
	
//	@Autowired
//	private AccountFlowService accountFlowService;

	@Autowired
	private UserActMysqlDAO userActMysqlDAO;
	@Autowired
	private UserInfoMysqlDAO userInfoMysqlDAO;
	           
	@Autowired
	private UserActFlowMysqlDAO userActFlowMysqlDAO;
	
	@Autowired
	private UserActFreezeMysqlDAO userFreezeMysqlDAO;
	
	@Autowired
	private UserBindCardMysqlDAO userBindCardMysqlDAO;
	
	@Autowired
	private OrderWithdrawMysqlDAO orderWithdrawMysqlDAO;
	
	@Autowired
	private OrderRechargeMysqlDAO orderRechargeMysqlDAO;
	
	@Autowired
	private OrderB2cMysqlDAO orderB2cMysqlDAO;
	
	@Autowired
	private GatewaySwiftCodeBankIdMappingMysqlDAO gatewaySwiftCodeBankIdMappingMysqlDAO;
	
	@Autowired
	private MqMessageService mqMessageService;
	
	@Autowired
	private UserInfoService userInfoService;
	
	@Autowired
	private ActService actService;
	
	@Autowired
	private DubboClientFactory dubboConsumerFactory;
	
	@Autowired  
	private TaskExecutor taskExecutor;// 线程池  
	
	@Autowired
	private UserRedisDAO userRedisDAO;
	
	@Autowired
	private LockRedisDAO lockRedisDAO;
	
	@Autowired
	OrderMappingService orderMappingService;
	
	@Autowired
	private BankUtilService bankUtilService;
	
	private SztfUserService sztfUserService = new SztfUserServiceImpl();	
	
	private SztfQueryService sztfQueryService = new SztfQueryServiceImpl();
	
	@Autowired
	@Qualifier("transactionManager")
	private DataSourceTransactionManager txManager;
	

	@Override
	public String createAct(String userId, Integer userType, Integer actType, String mobileNo, String attach) {		
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");
		
		List<UserType> userTypeList = UserType.listOf(userType);
		ValidateUtil.notEmpty(userTypeList, "用户类别参数有误");
		
		UserActType userActType = null;
		if (actType != null) {
			userActType = UserActType.valueOf(actType);	
			ValidateUtil.notNull(userActType, "账号类别参数有误");
			
		}
		
		if (StringUtil.isNotBlank(mobileNo)) {		
			ValidateUtil.isMobile(mobileNo, "用户手机号传入有误");
		}
		
		if (StringUtil.isNotBlank(attach)) {
			ValidateUtil.strMaxLen(attach, 255, "attach超过255个字符");
		}
				
		UserInfoDO userInfo = userInfoService.findUserInfo(userId);
		//查询账户是否已存在 		
		if (userInfo != null) {	//账户已存且账户状态正将直接将账户返回		
			int userState = userInfo.getUserStatus(); 			
			ValidateUtil.isNotTrue(userState == 0, "用户["+userId+"]已存在处于冻结中");
			
			UserInfoDO newUserInfo = null;
			
			int oldUserType = userInfo.getUserType();
			List<UserType> oldUserTypeList = UserType.listOf(oldUserType);			
			List<UserType> subList = (List<UserType>) CollectionUtils.subtract(userTypeList, oldUserTypeList);			
			if (subList != null && !subList.isEmpty()) { //用户角色有增加
				newUserInfo = new UserInfoDO();
				newUserInfo.setUserType(userType);
			}
			
			if (mobileNo != null) {
				if (!mobileNo.equals(userInfo.getMobile())) {
					if (newUserInfo == null) {
						newUserInfo = new UserInfoDO();
					}
					newUserInfo.setMobile(mobileNo);
				}
			}
			
			if (newUserInfo != null) {
				userInfoService.updateUserInfo(userId, newUserInfo);
			}
			
			if (userActType != null) {
				actService.createAct(userId, userType, actType);
			}else {
				actService.createUserAct(userId, userType);
			}
			
			return userId;
			
		}else {
			userInfo = new UserInfoDO();
			userInfo.setUserId(userId);
			userInfo.setUserType(userType);
			userInfo.setMobile(mobileNo);
			userInfo.setRemark(attach);	
			userInfo.setGrayState(1); //创建账户默认为灰度状态
			userInfoService.createUser(userInfo);		
			
			if (userActType != null) {
				actService.createAct(userId, userType, actType);
			}else {
				actService.createUserAct(userId, userType);
			}
			
			return userId;
		}
	}

	@Override
	public long queryBalance(String userId, Integer actType,boolean isCheckActStatus) {		
		UserActDO userActDO = queryAllBalance(userId, actType, isCheckActStatus);
		if(userActDO == null){
			return 0;
		}else{
			long realBalance = userActDO.getActBalance() - userActDO.getFreezeBalance();
			realBalance = realBalance < 0 ? 0 : realBalance;
			return realBalance;
		}
	}	
	
	
	@Override
	public UserActDO queryAllBalance(String userId, Integer actType,boolean isCheckActStatus) {		
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");
		
		UserActType userActType = UserActType.valueOf(actType);	
		ValidateUtil.notNull(userActType, "账号类别参数有误");
		String actTypeDesc = userActType.getDesc();
		if(userActType == UserActType.SZTF){
			throw new BusinessException("actType不能为1");
		}
		
		UserActDO userAct = actService.findUserAct(userId, userActType);
		//查询账户是否已存在 		
		if (userAct == null) {
			LOG.warn("用户"+userId+","+userActType.getDesc()+"不存在");
//			throw new BusinessException("用户["+userId+"]账户["+actType+"]不存在");
			return null;
		}
		
		int actState = userAct.getActState(); 	
		ValidateUtil.isNotTrue(actState == 3, "用户"+userId+","+actTypeDesc+"已注销");
		if(isCheckActStatus){
			ValidateUtil.isNotTrue(actState == 2, "用户"+userId+","+actTypeDesc+"处于冻结中");	
			ValidateUtil.isNotTrue(actState != 1, "用户"+userId+","+actTypeDesc+"状态异常");
		}
		
		return userAct;
	}

	
	@Override
	public boolean openMerchant(String userId, Integer userType, String attach) {		
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");
		List<UserType> userTypeList = UserType.listOf(userType);
		ValidateUtil.notEmpty(userTypeList, "用户类别参数有误");
		
		UserActType userActType = UserActType.valueOf(userType);
		ValidateUtil.notNull(userActType, "账号类别参数有误");
		
		if (StringUtil.isNotBlank(attach)) {
			ValidateUtil.strMaxLen(attach, 255, "attach超过255个字符");
		}
		
		UserInfoDO userInfo = userInfoService.findUserInfo(userId);
		if (userInfo != null) {			
			Integer isRealName = userInfo.getIsRealName();
			if (isRealName == null || isRealName.intValue() != 1) { //用户未实名
				UserVO userVo = getUserInfo(userId);				
				if (userVo == null) {
					LOG.warn("用户{}在用户中心未找到", userId);
					throw new BusinessException("用户"+userId+"不存在");
				}
				
				String realName = userVo.getRealname();
				String identityNo = userVo.getIdentityid();
				String mobileNo = userVo.getMob();
				
				if (StringUtil.isBlank(realName)) {
					LOG.info("用户{}真实姓名{}为空", userId, realName);
					realName = null;
				}
				
				if (!IDCardUtil.isIDCard(identityNo)) {
					LOG.info("用户{}身份证号{}有误", userId, identityNo);
					identityNo = null;
				}
				
				if (realName != null && identityNo != null) {					
					if (StringUtil.isNotBlank(mobileNo)) {
						try {
							ValidateUtil.isMobile(mobileNo, "");
						} catch (Exception e) {
							mobileNo = null;
							LOG.warn("用户{}手机号{}格式不正确", userId, mobileNo);
						}
					}
					
					userInfoService.realName(userId, identityNo, realName, mobileNo, "admin", null);
				}
			}
			
			int userState = userInfo.getUserStatus(); 			
			ValidateUtil.isNotTrue(userState == 0, "用户["+userId+"]已存在处于冻结中");
			
			int oldUserType = userInfo.getUserType();
			List<UserType> oldUserTypeList = UserType.listOf(oldUserType);
			
			List<UserType> subList = (List<UserType>) CollectionUtils.subtract(userTypeList, oldUserTypeList);
			if (subList == null || subList.isEmpty()) {
				return true;
			}			
			actService.createUserAct(userId, userType);
			
			
			UserInfoDO newUserInfo = new UserInfoDO();
			
			String realName = userInfo.getRealName();
			String identityNo = userInfo.getIdentityNo();
			String mobileNo = userInfo.getMobile();
			
			if (StringUtil.isBlank(realName) || StringUtil.isBlank(identityNo)) {				
				UserVO userVo = getUserInfo(userId);				
				if (userVo == null) {
					LOG.warn("用户{}在用户中心未找到", userId);
					throw new BusinessException("用户"+userId+"不存在");
				}
				
				realName = userVo.getRealname();
				identityNo = userVo.getIdentityid();
				mobileNo = userVo.getMob();
				
				if (StringUtil.isBlank(realName)) {
					LOG.info("用户{}真实姓名{}有误", userId, realName);
					realName = null;
				}
				
				if (!IDCardUtil.isIDCard(identityNo)) {
					LOG.info("用户{}身份证号{}有误", userId, identityNo);
					identityNo = null;
				}
				
				if (StringUtil.isBlank(mobileNo)) {
					mobileNo = null;
				}
			}

			newUserInfo.setUserType(userType);
			newUserInfo.setRemark(attach);
			userInfoService.updateUserInfo(userId, newUserInfo );			
		}else {			
			throw new BusinessException("用户"+userId+"不存在");
		}
		
		return true;
	}

	
	@Override
	public String bindCard(String userId, BindInfo bindInfo,String gateWayChannelId,String routeNo, String clientSourceType) {
		String bindCardNo = null;
		
		ValidateUtil.isNotBlank(userId, "userId不能为空");
		ValidateUtil.notNull(bindInfo, "bindInfo不能为空");
		
		BindCardType bindType = bindInfo.getBindType();
		String channelId = bindInfo.getChannelId();
		channelId = channelId == null ? "10" : channelId;//test  兼容业务层没有传的情况    后面业务层要统一加上
		CardType cardType = bindInfo.getCardType();
		//支持绑定信用卡:clientSourceType为1,3或者缴费渠道
//		if(bindType == BindCardType.BIND_QUICK_PAY && cardType == CardType.CARD_CREDIT){
//			if ( !JFUtils.isJFChannel(channelId) && !checkclientSourceType(clientSourceType)) {
//				throw new BusinessException("当前渠道不允许绑定信用卡");				
//			}
//		}
		if(bindType == BindCardType.BIND_QUICK_PAY && !JFUtils.isJFChannel(channelId) && cardType == CardType.CARD_CREDIT){
			throw new BusinessException("当前渠道不允许绑定信用卡");
		}
		
		CardActType cardActType = bindInfo.getCardActType();
		String cardNo = bindInfo.getCardNo();
		String cvv = bindInfo.getCvv();
		String expireDate = bindInfo.getExpireDate();
		String realName = bindInfo.getRealName();
		String identityNo = bindInfo.getIdentityNo();
		String mobileNo = bindInfo.getMobileNo();
		String cardProvince = bindInfo.getCardProvince();
		String cardCity = bindInfo.getCardCity();
		String bankAddr = bindInfo.getBankAddr();
		Integer isWithdrawCard = bindInfo.getIsWithdrawCard();
		
		
		String autoRemark = bindInfo.getAutoRemark();
		String companyName = bindInfo.getCompanyName();
		String updateUser = bindInfo.getUpdateUser();
		String bankName = bindInfo.getBankName();
		String swiftCode = bindInfo.getSwiftCode();

		ValidateUtil.isNotTrue(bindType == null, "bindType不能为空");
		ValidateUtil.isNotBlank(cardNo, "cardNo不能为空");
		ValidateUtil.isNotBlank(channelId, "channelId不能为空");
		
		switch (bindType) {
		case BIND_QUICK_PAY:
			ValidateUtil.isNotBlank(realName, "realName不能为空");			
			ValidateUtil.isNotBlank(identityNo, "identityNo不能为空");//绑定快捷支付卡时不能为空
			ValidateUtil.isNotBlank(mobileNo, "mobileNo不能为空"); //绑定快捷支付卡时不能为空			
			ValidateUtil.notNull(cardActType, "cardActType不能为空");
			ValidateUtil.notNull(cardType, "cardType不能为空");
			
			ValidateUtil.isBetween(cardNo.length(), 16, 64, "cardNo参数传入有误");			
			ValidateUtil.isTrue(IDCardUtil.isIDCard(identityNo), "identityNo参数传入有误");
			ValidateUtil.isMobile(mobileNo, "mobileNo传入有误");
			
			UserInfoDO userInfo = userInfoService.findUserInfo(userId);
			if(userInfo == null){
				throw new BusinessException("未查询到账号【"+userId+"】");
			}
			if(userInfo.getIsRealName() != null && userInfo.getIsRealName()==1){
				String userRealName = userInfo.getRealName();
				if(!userRealName.equals(realName)){
					//throw new BusinessException("账号【"+userId+"】绑卡真实姓名必须与实名认证姓名相同");//为了测试方便，先取消限制，上线把限制放开
				}
			}
			
			
			
			if (isWithdrawCard != null) {
				ValidateUtil.isBetween(isWithdrawCard, 0, 1, "isWithdrawCard参数传入有误");
			}else {
				isWithdrawCard = 0;
			}
			
			switch (cardActType) {
			case CARD_ACT_PRIVATE:
				bindInfo.setCardProvince(null);
				bindInfo.setCardCity(null);
				break;
			case CARD_ACT_PUBLIC:
				ValidateUtil.isNotBlank(cardProvince, "对公银行卡cardProvince不能为空");
				ValidateUtil.isNotBlank(cardCity, "对公银行卡cardCity不能为空");
				break;
			}
			
			switch (cardType) {
			case CARD_DEBIT:   //借记卡
				bindInfo.setCvv(cvv);
				bindInfo.setExpireDate(null);
				break;
			case CARD_CREDIT:  //信用卡
				boolean jfChannel = JFUtils.isJFChannel(channelId);
				//支持绑定信用卡:clientSourceType为1,3或者缴费渠道
//				if (!jfChannel && !checkclientSourceType(clientSourceType)) throw new BusinessException("当前渠道不允许绑定信用卡!");
				if (!jfChannel) throw new BusinessException("当前渠道不允许绑定信用卡!");
				ValidateUtil.isNotBlank(cvv, "信用卡cvv不能为空");
				ValidateUtil.isNotBlank(expireDate, "信用卡expireDate不能为空");				
				ValidateUtil.isTrue(cvv.length() == 3, "cvv为卡后3位尾号");
				ValidateUtil.isDate(expireDate, "yyMM", "信用卡过期时间不正确");
				break;
			case CARD_DOUBLE:
				throw new BusinessException("cardType参数传入有错");
			}

			break;
		case BIND_WITHDRAW:
			
			ValidateUtil.isNotBlank(cardNo, "cardNo不能为空");
			ValidateUtil.isNotBlank(realName, "realName不能为空");
			
//			ValidateUtil.isNotBlank(identityNo, "identityNo不能为空");//绑定快捷支付卡时不能为空
//			ValidateUtil.isNotBlank(mobileNo, "mobileNo不能为空"); //绑定快捷支付卡时不能为空
			
			
			if (StringUtil.isNotBlank(identityNo)) {
				ValidateUtil.isTrue(IDCardUtil.isIDCard(identityNo), "identityNo参数传入有误");
			}
			
			if (StringUtil.isNotBlank(mobileNo)) {
				ValidateUtil.isMobile(mobileNo, "mobileNo传入有误");
			}
			
			ValidateUtil.notNull(cardActType, "cardActType不能为空");
			ValidateUtil.notNull(cardType, "cardType不能为空");
			
			switch (cardActType) {
			case CARD_ACT_PRIVATE:
				ValidateUtil.isBetween(cardNo.length(), 16, 64, "cardNo参数传入有误");
				break;
			case CARD_ACT_PUBLIC:
				ValidateUtil.isBetween(cardNo.length(), 6, 64, "cardNo参数传入有误");
				ValidateUtil.isNotBlank(cardProvince, "对公银行卡cardProvince不能为空");
				ValidateUtil.isNotBlank(cardCity, "对公银行卡cardCity不能为空");
				ValidateUtil.isNotBlank(bankAddr, "对公银行卡bankAddr不能为空");
				ValidateUtil.isNotBlank(bankName, "对公银行卡bankName不能为空");
				ValidateUtil.isNotBlank(swiftCode, "对公银行卡swiftCode不能为空");
				break;
			}
				
			ValidateUtil.isTrue(cardType == CardType.CARD_DEBIT, "提现卡只能绑定借记卡");
		
			break;
		case BIND_ALIPAY:			
			
			break;
		}
		
		String tmpcardNo = YHBFSensitiveEnc.sensitiveEnc(cardNo,"cardno");
		List<UserBindCardDO> bindCardDO = userBindCardMysqlDAO.findByCardNo(userId, bindType.getValue(), tmpcardNo);
		if (!CollectionUtils.isEmpty(bindCardDO)) {
			//绑卡状态，0未认证，1已认证, 2已解绑
			for (UserBindCardDO userBindCardDO : bindCardDO) {
				int status = userBindCardDO.getStatus();			
				if (status == 1) {
					throw new BusinessException("此卡已绑定!");
//					return userBindCardDO.getBindCardNo();
				}
			}
		}
		
		switch (bindType) {
			case BIND_QUICK_PAY:
				bindCardNo = newbindQuickPay(userId, bindInfo,gateWayChannelId,routeNo);
				break;
			case BIND_WITHDRAW:
				bindCardNo = bindWithdraw(userId, cardActType, cardNo, realName, 
						mobileNo, cardProvince, cardCity, cardType,bankAddr,
						autoRemark,companyName,identityNo,updateUser,bankName,swiftCode);
				break;
			case BIND_ALIPAY:
				bindCardNo = bindAlipay(userId, cardNo, realName);
				break;			
		}

		return bindCardNo;
	}
	
	
	private boolean checkclientSourceType(String clientSourceType) {
		if (StringUtils.isBlank(clientSourceType)) {
			return false;	
		}
		if (Integer.parseInt(clientSourceType) == 1 || Integer.parseInt(clientSourceType) == 3) {
			return true;
		}
		return false;
	}

	//绑定快捷支付
	private String bindQuickPay(String userId, BindInfo bindInfo){	
		CardActType cardActType = bindInfo.getCardActType();
		CardType cardType = bindInfo.getCardType();
		String cardNo = YHBFSensitiveEnc.sensitiveEnc(bindInfo.getCardNo(),"cardno");
		String cvv = bindInfo.getCvv();
		String expireDate = bindInfo.getExpireDate();
		//String realName = YHBFSensitiveEnc.sensitiveEnc(bindInfo.getRealName(), "realname");
		String realName = bindInfo.getRealName();
		String identityNo = YHBFSensitiveEnc.sensitiveEnc(bindInfo.getIdentityNo(), "identityno");
		String mobileNo = YHBFSensitiveEnc.sensitiveEnc(bindInfo.getMobileNo(),"mob");
		String cardProvince = bindInfo.getCardProvince();
		String cardCity = bindInfo.getCardCity();
		String channelId = bindInfo.getChannelId();
		Integer isWithdrawCard = bindInfo.getIsWithdrawCard();
		
		List<UserBindCardDO> bindCardDOs = userBindCardMysqlDAO.findByCardNo(userId, BindCardType.BIND_QUICK_PAY.getValue(), cardNo);
		
		if (!CollectionUtils.isEmpty(bindCardDOs)) {
			//绑卡状态，0未认证，1已认证, 2已解绑
			for (UserBindCardDO userBindCardDO : bindCardDOs) {
				int status = userBindCardDO.getStatus();			
				if (status == 1) {
					return userBindCardDO.getBindCardNo();
				}
			}
		}
		
		UserInfoDO userInfo = userInfoService.findUserInfo(userId);
		ValidateUtil.notNull(userInfo, "用户"+userId+"不存在");
		
		boolean isJfUser = JFUtils.isJFChannel(channelId);
		if (isJfUser) {			
			UserActDO actInfo = actService.findUserAct(userId, UserActType.JF);
			ValidateUtil.notNull(actInfo, "用户"+UserActType.JF.getDesc()+"不存在,不能通过"+channelId+"渠道绑卡");
		}
		
		
		BankCardInfo bankCardInfo = getBankCardInfo(cardNo);
		String bankName = bankCardInfo.getBankName();
		String bankType = bankCardInfo.getBankType();
		String swiftCode = bankCardInfo.getSwiftCode();

		String bindCardNo = billnoService.nexBindCardNo();
		Date mDate = new Date();

		UserBindCardDO bindCardDO = new UserBindCardDO();
		bindCardDO.setBankName(bankName);
		bindCardDO.setBankType(bankType);
		bindCardDO.setBindCardNo(bindCardNo);
		bindCardDO.setCardActType(cardActType.getValue());
		bindCardDO.setCardCity(cardCity);
		bindCardDO.setCardNo(cardNo);
		bindCardDO.setCardProvince(cardProvince);
		bindCardDO.setCardCity(cardCity);
		bindCardDO.setCreateTime(mDate);
		bindCardDO.setExpireDate(expireDate);
		bindCardDO.setIdentityNo(identityNo);
		bindCardDO.setIdentityType(IdCardType.IC_IDCARD.getCode());
		bindCardDO.setIsMainCard(0);
		bindCardDO.setMobileNo(mobileNo);
		bindCardDO.setModifyTime(mDate);
		bindCardDO.setRealName(realName);
		bindCardDO.setStatus(0); // 未验证
		bindCardDO.setSwiftCode(swiftCode);
		bindCardDO.setUserId(userId);
		bindCardDO.setBindType(BindCardType.BIND_QUICK_PAY.getValue());
		bindCardDO.setCardType(cardType.getValue());
		bindCardDO.setChannelId(channelId);
		bindCardDO.setIsWithdrawCard(isWithdrawCard);
		bindCardDO.setCardCvv(cvv);
		
		userBindCardMysqlDAO.save(bindCardDO);

		ReqBindBankCard req = new ReqBindBankCard();
		req.setOrderId(bindCardNo);	
		req.setUserId(userInfo.getUserId());
		req.setAccountId(userInfo.getUserId());//test
		
		BankCard bankCard = new BankCard();
		bankCard.setBankCardNo(cardNo);
		bankCard.setCardType(cardType.getValue());
		bankCard.setCvv(cvv);
		bankCard.setExpireDate(expireDate);
		bankCard.setIdNo(identityNo);
		bankCard.setIdType(IdCardType.IC_IDCARD.getCode()); //只认证身份证
		bankCard.setPhone(mobileNo);
		bankCard.setRealName(realName);
		req.setBankCard(bankCard);
		
		LOG.info("BindBankCard Request:"+JSONObject.toJSONString(req));
		
		BankCardBindingRpcService bankCardBindingRpcService = dubboConsumerFactory.getDubboClient("bankCardBindingRpcService");	
		RespBindBankCard  resp = bankCardBindingRpcService .bindBankCard(req);	
		
		LOG.info("BindBankCard Response:"+JSONObject.toJSONString(resp));
		if (resp == null || !RespBindBankCard.RC_OK.equals(resp.getResultCode())) {
			String errorMsg = resp == null ? "":resp.getResultMsg() == null ? "":resp.getResultMsg(); 
			throw new BusinessException("用户["+userId+"]绑定快捷卡[" + cardNo + "]失败:" + errorMsg);
		}
		
		return bindCardNo;		
	}
	
	
	
	
	private String getBankIdByCardNo(String cardNo){
		BankCardInfo bankCardInfo = getBankCardInfo(cardNo);
		String bankId = gatewaySwiftCodeBankIdMappingMysqlDAO.getBankIdBySwiftCode(bankCardInfo.getSwiftCode(), 2);
		if(bankId == null){
			String decCardNo = YHBFSensitiveEnc.sensitiveDec(cardNo,"cardno");
			throw new BusinessException("查询银行卡【"+decCardNo+"】信息失败");
		}
		return bankId;
	}
	//绑定快捷支付
	private String newbindQuickPay(String userId, BindInfo bindInfo,String gateWayChannelId,String routeNo){	
		CardActType cardActType = bindInfo.getCardActType();
		CardType cardType = bindInfo.getCardType();
		String cardNo = bindInfo.getCardNo();
		String encCardNo = YHBFSensitiveEnc.sensitiveEnc(bindInfo.getCardNo(),"cardno");
		String cvv = bindInfo.getCvv();
		String expireDate = bindInfo.getExpireDate();
		//String realName = YHBFSensitiveEnc.sensitiveEnc(bindInfo.getRealName(), "realname");
		String realName = bindInfo.getRealName();
		String identityNo = bindInfo.getIdentityNo();
		String encIdentityNo = YHBFSensitiveEnc.sensitiveEnc(bindInfo.getIdentityNo(),"identityno");
		String mobileNo = bindInfo.getMobileNo();
		String encMobileNo = YHBFSensitiveEnc.sensitiveEnc(bindInfo.getMobileNo(),"mob");
		String cardProvince = bindInfo.getCardProvince();
		String cardCity = bindInfo.getCardCity();
		String channelId = bindInfo.getChannelId();
		Integer isWithdrawCard = bindInfo.getIsWithdrawCard();
		String bankId = getBankIdByCardNo(encCardNo);
		
		List<UserBindCardDO> bindCardDOs = userBindCardMysqlDAO.findByCardNo(userId, BindCardType.BIND_QUICK_PAY.getValue(), encCardNo);
		
		if (!CollectionUtils.isEmpty(bindCardDOs)) {
			//绑卡状态，0未认证，1已认证, 2已解绑
			for (UserBindCardDO userBindCardDO : bindCardDOs) {
				int status = userBindCardDO.getStatus();			
				if (status == 1) {
					throw new BusinessException("此卡已绑定!");
//					return userBindCardDO.getBindCardNo();
				}
			}
		}
		
		UserInfoDO userInfo = userInfoService.findUserInfo(userId);
		ValidateUtil.notNull(userInfo, "用户"+userId+"不存在");
		
		boolean isJfUser = JFUtils.isJFChannel(channelId);
		UserActDO actInfo = null;
		if (isJfUser) {			
			actInfo = actService.findUserAct(userId, UserActType.JF);
			ValidateUtil.notNull(actInfo, "用户"+UserActType.JF.getDesc()+"不存在,不能通过"+channelId+"渠道绑卡");
		}else{
			actInfo = actService.findUserAct(userId, UserActType.CASH);
		}
		
		
		BankCardInfo bankCardInfo = getBankCardInfo(encCardNo);
		String bankName = bankCardInfo.getBankName();
		String bankType = bankCardInfo.getBankType();
		String swiftCode = bankCardInfo.getSwiftCode();

		String bindCardNo = billnoService.nexBindCardNo();
		Date mDate = new Date();

		UserBindCardDO bindCardDO = new UserBindCardDO();
		bindCardDO.setBankId(bankId);
		bindCardDO.setBankName(bankName);
		bindCardDO.setBankType(bankType);
		bindCardDO.setBindCardNo(bindCardNo);
		bindCardDO.setCardActType(cardActType.getValue());
		bindCardDO.setCardCity(cardCity);
		bindCardDO.setCardNo(encCardNo);
		bindCardDO.setCardProvince(cardProvince);
		bindCardDO.setCardCity(cardCity);
		bindCardDO.setCreateTime(mDate);
		bindCardDO.setExpireDate(expireDate);
		bindCardDO.setIdentityNo(encIdentityNo);
		bindCardDO.setIdentityType(IdCardType.IC_IDCARD.getCode());
		bindCardDO.setIsMainCard(0);
		bindCardDO.setMobileNo(encMobileNo);
		bindCardDO.setModifyTime(mDate);
		bindCardDO.setRealName(realName);
		bindCardDO.setStatus(0); // 未验证
		bindCardDO.setSwiftCode(swiftCode);
		bindCardDO.setUserId(userId);
		bindCardDO.setBindType(BindCardType.BIND_QUICK_PAY.getValue());
		bindCardDO.setCardType(cardType.getValue());
		bindCardDO.setChannelId(channelId);
		bindCardDO.setIsWithdrawCard(isWithdrawCard);
		bindCardDO.setCardCvv(cvv);
		
		userBindCardMysqlDAO.save(bindCardDO);

//		ReqBindBankCard req = new ReqBindBankCard();
//		req.setOrderId(bindCardNo);	
//		req.setUserId(userInfo.getUserId());
//		req.setAccountId(userInfo.getUserId());//test
//		
//		BankCard bankCard = new BankCard();
//		bankCard.setBankCardNo(cardNo);
//		bankCard.setCardType(cardType.getValue());
//		bankCard.setCvv(cvv);
//		bankCard.setExpireDate(expireDate);
//		bankCard.setIdNo(identityNo);
//		bankCard.setIdType(IdCardType.IC_IDCARD.getCode()); //只认证身份证
//		bankCard.setPhone(mobileNo);
//		bankCard.setRealName(realName);
//		req.setBankCard(bankCard);
		
//		LOG.info("BindBankCard Request:"+JSONObject.toJSONString(req));
//		
//		BankCardBindingRpcService bankCardBindingRpcService = dubboConsumerFactory.getDubboClient("bankCardBindingRpcService");	
//		RespBindBankCard  resp = bankCardBindingRpcService .bindBankCard(req);	
//		
//		LOG.info("BindBankCard Response:"+JSONObject.toJSONString(resp));
//		if (resp == null || !RespBindBankCard.RC_OK.equals(resp.getResultCode())) {
//			String errorMsg = resp == null ? "":resp.getResultMsg() == null ? "":resp.getResultMsg(); 
//			throw new BusinessException("用户["+userId+"]绑定快捷卡[" + cardNo + "]失败:" + errorMsg);
//		}
		
		
		
		
		
		
		
		
		
		
		
		PayCoreAccountInfo payerAccount = new PayCoreAccountInfo();
		TradeInfo tradeInfo = new TradeInfo();
		String payMappingOrderId = orderMappingService.addMappingOrder(bindCardNo, (byte) Constance.PayFlowType.PAY.getCode());

		
		
		
		
		payerAccount.setPayerUserId(userId);
		payerAccount.setPayerUserType(userInfo.getUserType());
		if(isJfUser){
			payerAccount.setPayerActType(UserActType.JF);
		}else{
			payerAccount.setPayerActType(UserActType.CASH);
		}
		payerAccount.setPayerActNo(actInfo.getActNo());
		// payerAccount.setActNo(payerActInfo.getActNo());

		payerAccount.setBankAct(cardNo);
		payerAccount.setBankId(bindCardDO.getBankId());
		payerAccount.setCardType(CardType.valueOf(bindCardDO.getCardType()));
		payerAccount.setIdentityType(IdCardType.valueOf(bindCardDO.getIdentityType()));
		payerAccount.setIdentityNo(identityNo);
		payerAccount.setMobile(mobileNo);
		payerAccount.setRealName(bindCardDO.getRealName());
		payerAccount.setBankName(bindCardDO.getBankName());
		payerAccount.setCardActType(CardActType.valueOf(bindCardDO.getCardActType()));

		if (CardType.CARD_CREDIT.getValue() == bindCardDO.getCardType()) {
			payerAccount.setBankActCvv(bindCardDO.getCardCvv());
			payerAccount.setBankActExpire(bindCardDO.getExpireDate());
		}
		
		
		
		tradeInfo.setAmount(Constance.BIND_CARD_DEFAULT_AMOUNT);
		tradeInfo.setGoodsDetail("快捷绑卡");
		tradeInfo.setGoodsName("快捷绑卡");
//		tradeInfo.setNotifyUrl(ConfigUtil.innerReturnUrl);
//		tradeInfo.setReturnUrl(ConfigUtil.innerReturnUrl);
		tradeInfo.setRemark("快捷支付绑卡");
		tradeInfo.setBankId(bindCardDO.getBankId());
		tradeInfo.setOrderType(Constance.TradeOrderType.B2C_TRADE_ORDER);
		tradeInfo.setOriginOrderNo(bindCardNo);
		// 此处传入映射订单号
		tradeInfo.setTradeOrderId(payMappingOrderId);
		tradeInfo.setBusinessType(Constance.BIND_CARD_BUSINESS_TYPE);
		
		tradeInfo.setGateWayChannelId(gateWayChannelId);
		
		if(JFUtils.isJFChannel(channelId) && StringUtil.isBlank(routeNo)){
			String jfRouteNo = JFUtils.getJfDefaultRouteNo(2);
			tradeInfo.setRouteNo(jfRouteNo);
		}else if(StringUtil.isNotBlank(routeNo)){
			tradeInfo.setRouteNo(routeNo);
		}
		
		PayCoreResult result = payCoreService.pay(payerAccount, tradeInfo, "accountServiceImpl");
		
		PayFlowState payFlowState = PayFlowState.valueOf(result.getTradeSataus());
		if(payFlowState == PayFlowState.FAIL || payFlowState == PayFlowState.EXCEPTION){
			throw new BusinessException(result.getTradeDesc());
		}
		
		return bindCardNo;		
	}

	//绑定支付宝
	private String bindAlipay(String userId, String cardNo,  String realName){
		cardNo = YHBFSensitiveEnc.sensitiveEnc(cardNo,"cardno");
		//realName = YHBFSensitiveEnc.sensitiveEnc(realName, "realname");
		
		
		List<UserBindCardDO> bindCardDOs = userBindCardMysqlDAO.findByCardNo(userId, BindCardType.BIND_ALIPAY.getValue(), cardNo);
		
		if (!CollectionUtils.isEmpty(bindCardDOs)) {
			//绑卡状态，0未认证，1已认证, 2已解绑
			for (UserBindCardDO userBindCardDO : bindCardDOs) {
				int status = userBindCardDO.getStatus();			
				if (status == 1) {
					return userBindCardDO.getBindCardNo();
				}else if (status == 2) { //已解绑则直接更新装态返回
					
					UserBindCardDO updateUserbind = new UserBindCardDO();
					
					updateUserbind.setStatus(1);
					updateUserbind.setModifyTime(new Date());
					
					userBindCardMysqlDAO.updateBindCard(updateUserbind, userBindCardDO.getBindCardNo());
					return userBindCardDO.getBindCardNo();
					
				}
			}
		} 		
		
		UserBindCardDO bindCardDO = new UserBindCardDO();			
		String bindCardNo = billnoService.nexBindCardNo();	
		Date mDate = new Date();
		bindCardDO.setRealName(realName);
		bindCardDO.setUserId(userId);
		bindCardDO.setBindType(BindCardType.BIND_ALIPAY.getValue());
		bindCardDO.setCardNo(cardNo);
		bindCardDO.setStatus(1);//支付宝账号默认通过验证
		bindCardDO.setBindCardNo(bindCardNo);
		bindCardDO.setModifyTime(mDate);
		bindCardDO.setCreateTime(mDate);
		userBindCardMysqlDAO.save(bindCardDO);
		return bindCardDO.getBindCardNo();
		
	}
	
	
	//绑定提现卡
	private String bindWithdraw(String userId, CardActType cardActType, String cardNo,  
			String realName, String mobileNo, String cardProvince, 
			String cardCity, CardType cardType,String bankAddr,
			String autoRemark,String companyName,String identityNo,
			String updateUser,String bankName,String swiftCode){
		cardNo = YHBFSensitiveEnc.sensitiveEnc(cardNo,"cardno");
		//realName = YHBFSensitiveEnc.sensitiveEnc(realName, "realname");
		mobileNo = YHBFSensitiveEnc.sensitiveEnc(mobileNo,"mob");
		identityNo = YHBFSensitiveEnc.sensitiveEnc(identityNo,"identityno");
		List<UserBindCardDO> bindCardDOs = userBindCardMysqlDAO.findByCardNo(userId, BindCardType.BIND_WITHDRAW.getValue(), cardNo);
		if (!CollectionUtils.isEmpty(bindCardDOs)) {
			for (UserBindCardDO userBindCardDO : bindCardDOs) {
				int status = userBindCardDO.getStatus();			
				if (status == 1) {
					throw new BusinessException("此卡已绑定!");
//					return userBindCardDO.getBindCardNo();
				}else if (status == 2) { //已解绑则直接更新装态返回
					
					UserBindCardDO updateUserbind = new UserBindCardDO();
					
					updateUserbind.setStatus(1);
					updateUserbind.setModifyTime(new Date());
					updateUserbind.setRealName(realName);
					updateUserbind.setMobileNo(mobileNo);
					if(cardActType == CardActType.CARD_ACT_PUBLIC){
						if(identityNo != null)updateUserbind.setIdentityNo(identityNo);
						if(cardProvince != null)updateUserbind.setCardProvince(cardProvince);
						if(cardCity != null)updateUserbind.setCardCity(cardCity);
						if(mobileNo != null)updateUserbind.setMobileNo(mobileNo);
						if(realName != null)updateUserbind.setRealName(realName);
						if(bankAddr != null)updateUserbind.setBankAddr(bankAddr);
						if(autoRemark != null)updateUserbind.setAutoRemark(autoRemark);
						if(companyName != null)updateUserbind.setCompanyName(companyName);
						if(updateUser != null)updateUserbind.setOperator(updateUser);
						updateUserbind.setIdentityType(IdCardType.IC_IDCARD.getCode());
						updateUserbind.setIsMainCard(0);
						updateUserbind.setModifyTime(new Date());
						updateUserbind.setStatus(1);    //提现卡默认验证通过

					}
					
					userBindCardMysqlDAO.updateBindCard(updateUserbind, userBindCardDO.getBindCardNo());
					return userBindCardDO.getBindCardNo();
					
				}
			}
		}
		
		/*if(cardActType == CardActType.CARD_ACT_PUBLIC){
			List<UserBindCardDO> userMchBindList = userBindCardMysqlDAO.listMchBindCardInfo(userId, null, 1, null, null, null);
			if(userMchBindList.size() > 0){
				throw new BusinessException("该帐号【"+userId+"】已经绑定了至少一张企业银行卡,不允许重复绑定");
			}
		}*/
		
		String bankType = null;
		if(StringUtil.isBlank(bankName) || StringUtil.isBlank(bankName)){
			BankCardInfo bankCardInfo = getBankCardInfo(cardNo);	
			bankName = bankCardInfo.getBankName();
			bankType = bankCardInfo.getBankType();
			swiftCode = bankCardInfo.getSwiftCode();
		}
	
		
		String bindCardNo = billnoService.nexBindCardNo();			
		Date mDate = new Date();

		UserBindCardDO bindCardDO = new UserBindCardDO();	
		bindCardDO.setBindType(BindCardType.BIND_WITHDRAW.getValue());
		bindCardDO.setBankName(bankName);
		bindCardDO.setBankType(bankType);
		bindCardDO.setBindCardNo(bindCardNo);
		bindCardDO.setCardActType(cardActType.getValue());
		bindCardDO.setCardCity(cardCity);
		bindCardDO.setCardNo(cardNo);
		bindCardDO.setCardProvince(cardProvince);
		bindCardDO.setCardCity(cardCity);
		bindCardDO.setCreateTime(mDate);
		bindCardDO.setIdentityType(IdCardType.IC_IDCARD.getCode());
		bindCardDO.setIsMainCard(0);
		bindCardDO.setMobileNo(mobileNo);
		bindCardDO.setModifyTime(mDate);
		bindCardDO.setRealName(realName);
		bindCardDO.setStatus(1);    //提现卡默认验证通过
		bindCardDO.setSwiftCode(swiftCode);
		bindCardDO.setUserId(userId);
		bindCardDO.setCardType(cardType.getValue());
		bindCardDO.setOperator(updateUser);
		if(cardActType == CardActType.CARD_ACT_PUBLIC){
			bindCardDO.setBankAddr(bankAddr);
			bindCardDO.setAutoRemark(autoRemark);
			bindCardDO.setCompanyName(companyName);
			bindCardDO.setIdentityNo(identityNo);
		}
		if(StringUtil.isNotBlank(swiftCode)){
			String bankId = gatewaySwiftCodeBankIdMappingMysqlDAO.getBankIdBySwiftCode(swiftCode, 6);
			bindCardDO.setBankId(bankId);
		}
		userBindCardMysqlDAO.save(bindCardDO);
		
		return bindCardDO.getBindCardNo();
	}

	
	private BankCardInfo getBankCardInfo(String cardNo){
		
		ReqGetBankCardInfo requestBankCardInfo = new ReqGetBankCardInfo();
		requestBankCardInfo.setBankCardNo(cardNo);
		BankUtilRpcService bankUtilRpcService = dubboConsumerFactory.getDubboClient("bankUtilRpcService");
		
		LOG.info("GetBankCardInfo Request:"+JSONObject.toJSONString(requestBankCardInfo));
		RespGetBankCardInfo respBankCardInfo = bankUtilRpcService .getBankCardInfo(requestBankCardInfo);
		if (respBankCardInfo == null) {
			LOG.error("get bank card info not response.");
			throw new BusinessException("服务器忙，请稍后再试");
		}
		LOG.info("getBankCardInfo Response:"+JSONObject.toJSONString(respBankCardInfo));
		
		String resultCode = respBankCardInfo.getResultCode();
		String resultMsg = respBankCardInfo.getResultMsg();
		
		if (!RespBindBankCard.RC_OK.equals(resultCode)) {			
			LOG.warn("get bank card info error."+resultMsg);
			throw new BusinessException(resultMsg);
		}
		
		return respBankCardInfo.getCardInfo();		
	}

	@Override
	public String findRealActNo(String userId, Integer actType) {
		UserActDO userAct = findRealActInfo(userId, actType);
		return userAct.getActNo();
	}	

	@Override
	public UserActDO findRealActInfo(String userId, Integer actType) {
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");
		UserActType userActType = UserActType.valueOf(actType);
		ValidateUtil.notNull(userActType, "账号类别参数有误");	
		String errorInfo = "";
		
		UserActDO userAct = actService.findUserAct(userId, userActType);
		if (userAct == null) {			
			errorInfo = "用户["+userId+"]"+userActType.getDesc()+"不存在";			
			throw new BusinessException(errorInfo);
		}
		
//		int actState = userAct.getActState();
//		ValidateUtil.isNotTrue(actState  == ActState.STOP_PAY.getCode(), "用户["+userId+"]账户["+actType+"]已存在处于冻结中");
//		ValidateUtil.isNotTrue(actState == ActState.CANCELLATION.getCode(), "用户["+userId+"]账户["+actType+"]已存在但已注销");
//		ValidateUtil.isNotTrue(actState != ActState.NORMAL.getCode(), "用户["+userId+"]账户["+actType+"]状态异常");
		
//		Integer actLevel = userAct.getActLevel();
//		if (actLevel == null || actLevel <= 1) {
//			throw new BusinessException( "用户["+userId+"]账户["+userAct.getActNo()+"]未实名认证不允许该交易");
//		}
		
		return userAct;
	}


	@Override
	public UserBindCardDO findUserBindInfo(String bindNo, String userId,
			BindCardType bindCardType) {
		Integer bindCardValue = bindCardType != null ? bindCardType.getValue() : null;
		UserBindCardDO cardInfo = userBindCardMysqlDAO.findByBindCardNo(userId, bindCardValue, bindNo);		
		//解密敏感数据
		bindCardDODec(cardInfo);

		if (cardInfo == null ) {
			throw new BusinessException("用户["+userId+"]绑定号["+bindNo+"]不存在");
		}
		
		//0未认证，1已认证, 2已解绑
		int status = cardInfo.getStatus();
		if (status == 0) {			
			throw new BusinessException("用户["+userId+"]绑定号["+bindNo+"]未认证");
		}else if (status == 2) {
			throw new BusinessException("用户["+userId+"]绑定号["+bindNo+"]已解绑");
		}
		
		return cardInfo;
	}
	
	@Override
	public UserBindCardDO findUserBindInfoIgnoreState(String bindNo, String userId,
			BindCardType bindCardType) {
		Integer bindCardValue = bindCardType != null ? bindCardType.getValue() : null;
		UserBindCardDO cardInfo = userBindCardMysqlDAO.findByBindCardNo(userId, bindCardValue, bindNo);		
		//解密敏感数据
		bindCardDODec(cardInfo);

		if (cardInfo == null ) {
			return null;
		}
		
		return cardInfo;
	}
	
	
	private UserVO getUserInfo(String userId){		
		ValidateUtil.isNotBlank(userId, "用户Id不能为空");	
		
		try {
			QueryUserInfoService queryUserInfoService = dubboConsumerFactory.getDubboClient("queryUserInfoService");
			return queryUserInfoService.getUserInfo(userId);
		} catch (Exception e1) {
			LOG.error("", e1);
			throw new BusinessException("未查询到用户"+userId+"相关信息");
		}
	}
	
	
	
	@Override
	public String grayUser(String userId, String operator, String remark) {
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");

		UserActDO tfActInfo = actService.findUserAct(userId, UserActType.SZTF);
		UserInfoDO userInfo = userInfoService.findUserInfo(userId);
		
		if (userInfo == null) {				
			ValidateUtil.isNotBlank(operator, "操作人不能为空");			
			if (StringUtil.isNotBlank(remark)) {
				ValidateUtil.strMaxLen(remark, 200, "remark不能超过200个字符");
			}else {
				remark = "灰度迁移";
			}
			
			UserVO userVO = getUserInfo(userId);
			
			if (userVO == null) {
				ValidateUtil.notNull(userVO, "用户"+userId+"不存在");
			}			
			
			String realName = userVO.getRealname();    //真实姓名
			String identityNo = userVO.getIdentityid();  //身份证号
			String mobileNo = userVO.getMob();         //手机号
			String registerTime = userVO.getRegTime();     //注册时间
			int userType = userVO.getUserRole();    //用户角色			
			List<UserType> userTypeList = UserType.listOf(userType);
			ValidateUtil.notEmpty(userTypeList, "用户"+userId+"角色"+userType+"有误，不能灰度");
			
			if (StringUtil.isNotBlank(mobileNo)) {
				try {
					ValidateUtil.isMobile(mobileNo, "用户"+userId+"手机号"+mobileNo+"有误");
				} catch (Exception e) {
					LOG.warn(e.getMessage());
					mobileNo = null;
				}
			}
			
			Date regTime = null;
			if (StringUtil.isNotBlank(registerTime)) {
				try {
					regTime = DateUtil.parserStringToDate(registerTime, "yyyy-MM-dd HH:mm:ss");
				} catch (ParseException e) {			
					LOG.warn("用户"+userId+"注册时间格式有误");
				}
			}
			
			int isRealName = 0;
			
			String tfActNo = userId;	
			if (tfActInfo != null) { //原有商城用户
				tfActNo = tfActInfo.getChannelActNo();
				
				if (StringUtil.isBlank(mobileNo)) {
					mobileNo = null;
				}
				
				if (StringUtil.isBlank(realName)) {
					realName = null;
				}
				
				if (!IDCardUtil.isIDCard(identityNo)) {
					identityNo = null;
				}
				
				if (realName != null && identityNo != null) {
					isRealName = 1;
				}
			}else { //没有通付账户				
				ValidateUtil.isNotBlank(realName, "用户"+userId+"真实姓名为空,不能灰度");
				ValidateUtil.strMaxLen(realName, 100, "用户"+userId+"真实姓名超过100个字符,不能灰度");
				
				ValidateUtil.isNotBlank(identityNo, "用户"+userId+"身份证为空,不能灰度");
				ValidateUtil.isTrue(IDCardUtil.isIDCard(identityNo), "用户"+userId+"身份证"+identityNo+"不合法");	
				
				////通付账户不存在，先迁移通付账户
				MigrateUserRespData resp = tfTransfer(userId, true, mobileNo, realName, identityNo);
				tfActNo = resp.getUserId();
				
				LOG.info("用户"+userId+"在通付的账户不存在,创建通付账户");
				tfActInfo = createSztfAct(userId, tfActNo, "灰度用户迁移", UserActType.SZTF.getCode());	
				
				isRealName = 1;
				
			}
			
			QueryUserActRespData tfUserAct = queryTfBalance(tfActNo);
			int freezedBalance = tfUserAct.getFreezedBalance();
			int balance = tfUserAct.getBalance();  //可用余额   通付的账户余额-冻结金额
			
			userInfo = new UserInfoDO();
			userInfo.setUserId(userId);
			userInfo.setUserType(userType);
			userInfo.setMobile(mobileNo);		
			userInfo.setIsRealName(isRealName);
			userInfo.setIdentityNo(identityNo);
			userInfo.setRealName(realName);			
			userInfo.setRemark(remark);
			userInfo.setUpdateUser(operator);
			userInfo.setCreateTime(regTime);
			
			int grayState = 0;
			
			if (balance <= 0) {				
				grayState = 1;
			}else { //用户余额大于0				
//				if (balance < freezedBalance) { //冻结金额大于用户余额   属于异常状态
//					throw new BusinessException("用户"+userId+"在通付的余额为"+balance+",冻结金额为"+freezedBalance+",余额小于冻结金额，不能灰度该用户");
//				}else if (balance == freezedBalance) {
//					grayState = 1;
//				}else { 
					//用户有余额需要转移					
				if (isRealName != 1) {
					LOG.warn("用户"+userId+"未实名认证,不能灰度,realName="+realName+",identityNo="+identityNo+",balance="+balance+",freezedBalance="+freezedBalance);
					throw new BusinessException("用户"+userId+"未实名认证，不能灰度该用户");
				}
//				}
			}
			
			userInfo.setGrayState(grayState);
			
			//创建用户信息
			userInfoService.createUser(userInfo);	
			notifyUserCenterPayAct(userId);
	
			//创建用户的账户信息
			actService.createUserAct(userId, userType);
			
			if (grayState == 1) {
				LOG.info("用户"+userId+"在通付的余额为"+balance+",冻结金额为"+freezedBalance+",直接灰度该用户");
				
				taskExecutor.execute(new SyncBindCardInfo(userId, userType, LogMsgNoConverter.getCurrentMsgno()));
				
				return null;
			}
			
			//余额大于0的情况
			String userGrade = tfUserAct.getUserGrade();
			if (StringUtil.isBlank(userGrade)) {
				throw new BusinessException("该用户在通付的用户等级未知，不能灰度");
			}
				
			int uLevel = Integer.parseInt(userGrade);
			if (uLevel < 2) { //用户未实名认证 （正常情况不会有该分支）
				LOG.info("用户"+userId+"在通付的余额为"+balance+",冻结金额为"+freezedBalance+",直接灰度该用户");

				realSztfAuth(userId, realName, identityNo, mobileNo, tfActNo);
			}
			
			tranferUserBalance(userId, userType, tfActNo);
			
			
			
			
			
						
		} else {			
			/**
			 *该分支出现的可能是 
			 *1.新创建的用户
			 *  新创建的用户状态为灰度
			 *2.迁移未成功的用户
			 *
			 */
						
			//如果用户没有余额,直接更新灰度状态为1			
			Integer grade = userInfo.getGrade();
			if (grade != null && grade.intValue() == 1) { //用户已灰度
				LOG.info("用户"+userId+"已灰度");				
				return null;
			}
			
			Integer isRealName = userInfo.getIsRealName();
			if (isRealName == null || isRealName.intValue() != 1) {
				
				throw new BusinessException("用户未实名认证不允许灰度");				
			}		
		}
		return null;
	}
	
	
	/**
	 * 迁移用户在通付的余额
	 */
	private void tranferUserBalance(String userId, Integer userType, String tfActNo){
		QueryUserActRespData tfUserAct = queryTfBalance(tfActNo);
		int freezedBalance = tfUserAct.getFreezedBalance();		
		int balance = tfUserAct.getBalance();  //可用余额   通付的账户余额-冻结金额
		String userGrade = tfUserAct.getUserGrade();
		
		LOG.info("用户{}，当前余额为{}，冻结金额为{}", userId, balance, freezedBalance);
		
		if (StringUtil.isBlank(userGrade) || !StringUtil.isNumeric(userGrade)) {
			LOG.info("用户在通付的用户等级为{},不能处理", userGrade);
			throw new BusinessException("用户"+userId+"在通付实名等级有误");
		}
		
		if (Integer.parseInt(userGrade) < 2) {
			LOG.warn("用户在通付的用户等级为{}未实名认证,不能处理", userGrade);
			throw new BusinessException("用户"+userId+"在通付未实名认证");
		}
		
		if (balance <= 0) {
			LOG.info("用户当前余额为{}，不再做余额迁移", balance);
			return;
		}					
		
		
		if (balance < 1000000) { //账户余额小于1W
			transferBalance(userId, userType, tfActNo, balance);
		}else { //账户余额大于1W			
			int transferTimes = 1;			
			int tBalance = 900000;
			
			while (balance > 0) {				
				if (balance < tBalance) {
					tBalance = balance;
				}
				
				LOG.info("用户当前余额为{}，第{}次迁移余额，迁移金额为{}", balance, transferTimes, tBalance);
				transferBalance(userId, userType, tfActNo, tBalance);
				
				balance = balance - tBalance;
				transferTimes ++;
			}
		}		
	}
	
	
	
	private void transferBalance(String userId, Integer userType, String tfActNo, long balance){		
		//将用户余额转账到通行账户，并将加款用户账户相应余额				
		PayCoreTransfer payCoreTransfer = new PayCoreTransfer();
		String referOrderId = billnoService.nextNo(1025);
					
		String serviceName = "accountServiceImpl";
					
		payCoreTransfer.setAmount(balance);
		payCoreTransfer.setAttach("账户灰度迁移");
		payCoreTransfer.setInnerTransferType(InnerTransferType.C2B);
		payCoreTransfer.setReferOrderId(referOrderId);
		payCoreTransfer.setTradeOrderType(TradeOrderType.GRAY_USER);
					
		payCoreTransfer.setPayerAccountId(null);
		payCoreTransfer.setPayerTfActNo(tfActNo);
		payCoreTransfer.setPayerUserId(userId);
		payCoreTransfer.setPayerUserType(userType);
		payCoreTransfer.setPayerActType(Constance.UserActType.SZTF);
					
		payCoreTransfer.setPayeeAccountId(null);
		payCoreTransfer.setPayeeActType(UserActType.SZTF);
		payCoreTransfer.setPayeeTfActNo(Constance.ACT_SZTX_CASH);
		payCoreTransfer.setPayeeUserId(Constance.USER_ID_SZTX);
		payCoreTransfer.setPayeeUserType(UserType.SZTX.getCode());
		
		LOG.info("迁移用户{}在通付的余额{}",userId, balance);
		
		PayCoreResult payCoreResult = payCoreService.transfer(payCoreTransfer, serviceName, referOrderId);				
		if (payCoreResult != null && payCoreResult.getTradeSataus() == PayFlowState.SUCCESS.getCode()) {
			PayCoreTradeInfo tradeInfo = new PayCoreTradeInfo();
					
			tradeInfo.setAmount(balance);
			tradeInfo.setChannelId(payCoreResult.getChannelId());
			tradeInfo.setPayCoreOrderId(payCoreResult.getPayFlowNo());
			tradeInfo.setPayeeUserId(Constance.USER_ID_SZTX);
			tradeInfo.setPayeeUserType(UserType.SZTX.getCode());
			tradeInfo.setPayerUserId(userId);
			tradeInfo.setPayerUserType(userType);
			tradeInfo.setPayFlowDesc(payCoreResult.getTradeDesc());
			tradeInfo.setPayFlowState(PayFlowState.valueOf(payCoreResult.getTradeSataus()));
			tradeInfo.setPayFlowType(PayFlowType.TRANSFER);
			tradeInfo.setReferOrderId(referOrderId);
			tradeInfo.setTradeOrderType(TradeOrderType.GRAY_USER);
									
			callPayResult(tradeInfo);					
//			taskExecutor.execute(new SyncBindCardInfo(userId, userType));
		}else {
			
			LOG.info("用户"+userId+"余额迁移失败，结果:"+payCoreResult);
		}
	}

		
	/**
	 * 创建用户通付账户
	 * @param userId
	 * @param userType
	 * @param actType
	 * @param mobileNo
	 * @param attach
	 * @param innerRemark
	 * @param isCreateTfAct
	 * @return
	 */
	private UserActDO createSztfAct(String userId, String tfActNo, String innerRemark, int actType){
	
		String actNo = billnoService.nextUserAccount();
		
		UserActDO user = new UserActDO();
		Date nowTime = new Date();
		user.setActBalance(0l); //账户创建为0
		user.setActNo(actNo);
		user.setActState(1);
		user.setActType(actType);
		user.setBalanceTime(nowTime);		

		user.setCreateTime(nowTime);
		user.setFreezeBalance(0l);
		user.setInnerRemark(innerRemark);
		user.setModifyCount(0);
		user.setModifyTime(nowTime);
		user.setUserId(userId);
		user.setUserRemark("");
		
		user.setActLevel(Constance.ActLevel.LEVEL_V1.getCode());
		user.setChannelId(UserActType.SZTF.getChannelId());
		user.setChannelActNo(tfActNo);
		
		
		userActMysqlDAO.save(user);	
		return user;
	}
	

	//账户灰度
	@Override
	public String transferUser(String userId, Integer userType, boolean isRealName, String mobileNo, String realName, String identityNo,String lastOperator,String remark) {		
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");
		List<UserType> userTypeList = UserType.listOf(userType);
		
		ValidateUtil.notEmpty(userTypeList, "userType参数错误");
		if (isRealName) {
//			ValidateUtil.isNotBlank(mobileNo, "实名认证用户mobileNo不能为空");					
			if (StringUtil.isNotBlank(mobileNo)) {
				ValidateUtil.isMobile(mobileNo, "用户手机号传入有误");
			}else{
				mobileNo = null;
			}
					
			ValidateUtil.isNotBlank(realName, "实名认证用户realName不能为空");			
			ValidateUtil.strMaxLen(realName, 100, "realName超过100个字符");
			
			ValidateUtil.isNotBlank(identityNo, "实名认证用户identityNo不能为空");						
			ValidateUtil.isTrue(IDCardUtil.isIDCard(identityNo), "identityNo不合法");			
		}else {
			mobileNo = null;
			realName = null;
			identityNo = null;
		}	
	
		UserActDO tfActInfo = actService.findUserAct(userId, UserActType.SZTF);
		UserInfoDO userInfo = userInfoService.findUserInfo(userId);

		if (userInfo == null) { //用户信息不存在				
			userInfo = new UserInfoDO();
			userInfo.setUserId(userId);
			userInfo.setUserType(userType);
			userInfo.setMobile(mobileNo);		
			userInfo.setIsRealName(isRealName ? 1 :0);
			userInfo.setIdentityNo(identityNo);
			userInfo.setRealName(realName);			
			userInfo.setRemark("灰度迁移");
			userInfo.setGrayState(0);
			userInfo.setUpdateUser(lastOperator);
			userInfoService.createUser(userInfo);			
			List<CreateActRep> actList = actService.createUserAct(userId, userType);
			
			String tfActNo = userId;			
			if (tfActInfo == null) { //通付账户不存在，先迁移通付账户
				MigrateUserRespData resp = tfTransfer(userId, isRealName, mobileNo, realName, identityNo);
				tfActNo = resp.getUserId();

//				userActFlowMysqlDAO.save(t);
				
			}else {
				tfActNo = tfActInfo.getChannelActNo();
			}
			
			QueryUserActRespData tfUserAct = queryTfBalance(tfActNo);
			int freezedBalance = tfUserAct.getFreezedBalance();
			int balance = tfUserAct.getBalance();
			
			if (freezedBalance > 0) {
				throw new BusinessException("该用户在通付有冻结金额，不能灰度");
			}
			
			if (balance > 0) { //用户在通付有余额
				String userGrade = tfUserAct.getUserGrade();
				if (StringUtil.isBlank(userGrade)) {
					throw new BusinessException("该用户在通付的用户等级未知，不能灰度");
				}
				
				int uLevel = Integer.parseInt(userGrade);
				if (uLevel < 2) { //用户未实名认证
					if (!isRealName) {
						throw new BusinessException("该用户在通付未实名认证，不能灰度");
					}
					realSztfAuth(userId, realName, identityNo, mobileNo, tfActNo);
				}
				
				//将用户余额转账到通行账户，并将加款用户账户相应余额
				
				PayCoreTransfer payCoreTransfer = new PayCoreTransfer();
				
				String referOrderId = billnoService.nextNo(1025);
				
				String serviceName = "accountServiceImpl";
//				String referOrderId = com.sztx.se.common.util.date.DateUtil.formatDate(new Date(), "yyyyMMddHHmmss")+userId;
				
				payCoreTransfer.setAmount(balance);
				payCoreTransfer.setAttach("账户灰度迁移");
				payCoreTransfer.setInnerTransferType(InnerTransferType.C2B);
				payCoreTransfer.setReferOrderId(referOrderId);
				payCoreTransfer.setTradeOrderType(TradeOrderType.GRAY_USER);
				
				payCoreTransfer.setPayerAccountId(null);
				payCoreTransfer.setPayerTfActNo(tfActNo);
				payCoreTransfer.setPayerUserId(userId);
				payCoreTransfer.setPayerUserType(userType);
				payCoreTransfer.setPayerActType(Constance.UserActType.SZTF);
				
				payCoreTransfer.setPayeeAccountId(null);
				payCoreTransfer.setPayeeActType(UserActType.SZTF);
				payCoreTransfer.setPayeeTfActNo(Constance.ACT_SZTX_CASH);
				payCoreTransfer.setPayeeUserId(Constance.USER_ID_SZTX);
				payCoreTransfer.setPayeeUserType(UserType.SZTX.getCode());
				
				PayCoreResult payCoreResult = payCoreService.transfer(payCoreTransfer, serviceName, referOrderId);
				
				if (payCoreResult != null && payCoreResult.getTradeSataus() == PayFlowState.SUCCESS.getCode()) {
					PayCoreTradeInfo tradeInfo = new PayCoreTradeInfo();
					tradeInfo.setAmount(balance);
					tradeInfo.setChannelId(payCoreResult.getChannelId());
					tradeInfo.setPayCoreOrderId(payCoreResult.getPayFlowNo());
					tradeInfo.setPayeeUserId(Constance.USER_ID_SZTX);
					tradeInfo.setPayeeUserType(UserType.SZTX.getCode());
					tradeInfo.setPayerUserId(userId);
					tradeInfo.setPayerUserType(userType);
					tradeInfo.setPayFlowDesc(payCoreResult.getTradeDesc());
					tradeInfo.setPayFlowState(PayFlowState.valueOf(payCoreResult.getTradeSataus()));
					tradeInfo.setPayFlowType(PayFlowType.TRANSFER);
					tradeInfo.setReferOrderId(referOrderId);
					tradeInfo.setTradeOrderType(TradeOrderType.GRAY_USER);
								
					callPayResult(tradeInfo );
				}else {
					LOG.info("用户"+userId+"余额迁移结果:"+payCoreResult);
				}
			} else {
				//如果用户没有余额,直接更新灰度状态为1
				UserInfoDO newUserInfo = new UserInfoDO();
				newUserInfo.setGrayState(1);
				
				userInfoService.updateUserInfo(userId, newUserInfo );
			}
		}else {			
			int grayState = userInfo.getGrayState();
			if (grayState == 1) {//用户已灰度
				return userId;
			}
			
			//用户未灰度
			if (isRealName) {
				
			}
			
			
			
			
			
			Integer userLevel = userInfo.getIsRealName();
			if (userLevel == 0 ) {
				
			}
			
			
		}
		
		
		
		
		
		
		
//		UserActDO updateUserAct = new UserActDO();
//		updateUserAct.setChannelId(Constance.CHANNEL_ID_SZTF);
//		updateUserAct.setChannelActNo(channelActNo);
//		int actLevel = Constance.ActLevel.LEVEL_V1.getCode();
//		if (isRealName) {
//			actLevel = Constance.ActLevel.LEVEL_V2.getCode();
//		}
//		updateUserAct.setActLevel(actLevel);
//		updateUserAct.setModifyTime(new Date());
//		userActMysqlDAO.updateAct(updateUserAct, actNo);
//		
//		syncFreezedBalance(actNo, channelActNo, userId);
//		
//		
//		transferBindCard(userId);
//		transferWithdrawBankList(userId);
//		
//		
//		try {
//			String url = ConfigUtil.getTransferUserNotifyUrl();
//			url = String.format(url,userAct.getUserId(),userAct.getActNo() );
//			Log.info("mangeToNew url:"+url);
//			HttpClientUtil.get(url);
//		} catch (Exception e) {
//			LOG.info("用户迁移通知新用户中心异常,userId:"+userAct.getUserId(),e);
//		}
//		
//		return actNo;
		
		return null;
	}
	
	
	
	private MigrateUserRespData tfTransfer(String userId, boolean isRealName, String mobileNo, String realName, String identityNo){
		MigrateUserReqData request = new MigrateUserReqData();		
		request.setOutUserId(userId);
		request.setIsRealName((isRealName ? "YES":"NO"));
		request.setMobileNo(mobileNo);
		request.setRealName(realName);
		request.setIdentityNo(identityNo);
		request.setMerId(Constance.SZTX_MER_ID);
		
		request.setRiskParams(getTfRiskParams());
		
//		if (!userId.equals("1898858") && !userId.equals("7821813") && !userId.equals("34359670") ) {
		try {
			LOG.info("TransferUser request:" + JSONObject.toJSONString(request));
			MigrateUserRespData resp = sztfUserService.migrateUser(request);
			if (resp == null) {
				LOG.error("通付账户" + userId + "迁移无响应");
				throw new BusinessException("用户账户" + userId + "迁移失败");
			}
			LOG.info("TransferUser response:" + JSONObject.toJSONString(resp));
			
			if (!Constance.PAY_SDK_SZTF_RESULT_SUCCESS.equals(resp.getRspCode())) {
				throw new BusinessException(resp.getRspMsg());
			}	
			
			
			String rspMsg = resp.getRspMsg();
			String channelActNo = resp.getUserId();
			ValidateUtil.isNotBlank(channelActNo, "用户账户" + userId + "迁移失败," + rspMsg);

			return resp;
		} catch (Exception e) {
			LOG.error("用户账户" + userId + "迁移失败", e);
			throw new BusinessException("用户账户" + userId + "迁移失败");
		}
	}
	
	
	
	

	@Override
	public boolean realAuth(String userId, ActLevel actLevel, String realName, String identityNo, String mobileNo) {
		
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");
		
		ValidateUtil.isNotBlank(mobileNo, "实名认证用户mobileNo不能为空");		
		ValidateUtil.isMobile(mobileNo, "用户手机号传入有误");
			
		ValidateUtil.isNotBlank(realName, "实名认证用户realName不能为空");			
		ValidateUtil.strMaxLen(realName, 100, "realName超过100个字符");
			
		ValidateUtil.isNotBlank(identityNo, "实名认证用户identityNo不能为空");						
		ValidateUtil.isTrue(IDCardUtil.isIDCard(identityNo), "identityNo不合法");		
						
//		UserActDO userAct = userActMysqlDAO.findByUserId(userId, ActType.BALANCE_ACT.getCode());
		
		UserInfoDO userInfo = userInfoService.findUserInfo(userId);
		
		
		if (userInfo == null) {
			throw new BusinessException("用户["+userId+"]余额账户不存在");
		}
	
		if (userInfo.getIsRealName() == 1) { //用户已实名认证过			
			return true;
		}
		
		userInfoService.realName(userId, identityNo, realName, mobileNo, "admin", null);
		
		return true;
//		return realSztfAuth(userId, realName, identityNo, mobileNo, actNo, channelActNo, channelId);
		
		
	}
	
	
	
	
	private RealAuthRespData realSztfAuth(String userId, String realName, String identityNo, String mobileNo, String channelActNo){
		RealAuthReqData request = new RealAuthReqData();
		request.setRiskParams(getTfRiskParams());
		request.setUserId(channelActNo);
		request.setIdentityNo(identityNo);
		request.setLevel("V2");
		request.setIdentityType("SFZ");
		request.setMobileNo(mobileNo);
		request.setRealName(realName);
		request.setMerId(Constance.SZTX_MER_ID);		
		
		try {
			LOG.info("RealAuth request:"+JSONObject.toJSONString(request));
			RealAuthRespData resp = sztfUserService.realAuth(request);	
			if (resp == null) {
				LOG.error("账户"+userId+"实名认证通付无响应");
				throw new BusinessException("账户"+userId+"实名认证失败");
			}
			LOG.info("RealAuth response:"+JSONObject.toJSONString(resp));
			String rspCode = resp.getRspCode();
			String rspMsg = resp.getRspMsg();
			if (!Constance.PAY_SDK_SZTF_RESULT_SUCCESS.equals(rspCode)) {
				LOG.error("账户"+userId+"实名认失败，errorCode="+rspCode+",errorMsg="+rspMsg);
				throw new BusinessException("账户"+userId+"实名认证失败");
			}
			
			return resp;
		} catch (Exception e) {
			LOG.error("用户账户"+userId+"实名认证失败", e);
			throw new BusinessException("用户账户"+userId+"实名认证失败");
		}
	}
	
	
	
	
	private void transferBindCard(String userId, String channelId){
		
		LOG.info("开始同步用户{}在通付的快捷支付绑卡信息", userId);
		
		MsgSrvProxyFacade msgSrvProxyFacade = dubboConsumerFactory.getDubboClient("msgSrvProxyFacade");
		
		JSONObject data = new JSONObject();
		data.put("userId", userId);
		data.put("bindType", 1);
		
		String connId = UUIDUtil.getNumUUID();
		
		String msg = MsgSrvUtil.createMessage("mobileQuickPayFacade", connId, "findBindCardList", data.toJSONString());
		ProxyRequestParam param = new ProxyRequestParam(3, connId, 1, msg); // 3:新支付msgsrv，1:长连接
		String response = msgSrvProxyFacade.getResult(param);
		
		if (StringUtil.isBlank(response)) {			
			LOG.warn("Request user bind card list no response");
			return;
		}
		MsgSrvRsp rsp = new MsgSrvRsp(response);
		String resultCode = rsp.getString("resultCode");
		
		try {
			if ("1001".equals(resultCode)) {
				byte[] d = Base64.decodeBase64(rsp.getString("data"));
				response = new String(d, "GBK");
				
				LOG.info("response:"+response);
				List<TfBindQuickPay> quickPayList = JSONObject.parseArray(response, TfBindQuickPay.class);	
				LOG.info("quickPayList:"+JSONObject.toJSONString(quickPayList));
				List<UserBindCardDO> bindCardList = null;
				
				if (quickPayList != null && !quickPayList.isEmpty()) {
					
					List<UserBindCardDO> userBindCardDOs = queryBindCardList(userId, 1);
					
					Map<String, UserBindCardDO> oldQuickPayCard = new HashMap<String, UserBindCardDO>();
					
					if (userBindCardDOs != null && !userBindCardDOs.isEmpty()) {
						for (UserBindCardDO userBindCardDO : userBindCardDOs) {
							oldQuickPayCard.put(userBindCardDO.getCardNo(), userBindCardDO);
						}
					}
					
					
					for (TfBindQuickPay tfBindQuickPay : quickPayList) {
						
						if (tfBindQuickPay.getStatus() == null || tfBindQuickPay.getStatus().intValue() != 1) {
							LOG.info("用户快捷支付绑卡数据无效：tfBindQuickPay="+tfBindQuickPay);
							continue;
						}
						
						
						
						
						String tfBankCard = null;
						if (StringUtil.isNotBlank(tfBindQuickPay.getBankCard())){
							tfBankCard = YHBFUtil.decrypt(tfBindQuickPay.getBankCard());
						}else{
							LOG.error("卡号为空，无法进行迁移  ：tfBindQuickPay="+tfBindQuickPay);
							continue;
						}
						
						if (oldQuickPayCard.containsKey(tfBankCard) && 1 == tfBindQuickPay.getBankChannel()) {
							LOG.error("该快捷支付卡系统已经存在，无需迁移：tfBindQuickPay="+tfBindQuickPay);
							continue;
						}
						
						if (StringUtil.isNotBlank(tfBindQuickPay.getBankCard())) {
							tfBindQuickPay.setBankCard(YHBFUtil.decrypt(tfBindQuickPay.getBankCard()));
						}
						
						if (StringUtil.isNotBlank(tfBindQuickPay.getIdentityNo())) {
							tfBindQuickPay.setIdentityNo(YHBFUtil.decrypt(tfBindQuickPay.getIdentityNo()));
						}
						
						if (StringUtil.isNotBlank(tfBindQuickPay.getMobileNo())) {
							tfBindQuickPay.setMobileNo(YHBFUtil.decrypt(tfBindQuickPay.getMobileNo()));
						}
					
						String bindCardNo = billnoService.nexBindCardNo();	
						
						UserBindCardDO bindCardDO = new UserBindCardDO();		
						bindCardDO.setBankName(tfBindQuickPay.getBankName());
//						bindCardDO.setBankType(bankType);
						bindCardDO.setBindCardNo(bindCardNo);
						bindCardDO.setCardActType(CardActType.CARD_ACT_PRIVATE.getValue());
//						bindCardDO.setCardCity(cardCity);
						bindCardDO.setCardNo(YHBFSensitiveEnc.sensitiveEnc(tfBindQuickPay.getBankCard(),"cardno"));
//						bindCardDO.setCardProvince(cardProvince);
//						bindCardDO.setCardCity(cardCity);
						bindCardDO.setCreateTime(new Date(tfBindQuickPay.getCreateTime()));
						bindCardDO.setExpireDate(tfBindQuickPay.getExpireDate());
						bindCardDO.setCardCvv(tfBindQuickPay.getCvv());
						bindCardDO.setIdentityNo(YHBFSensitiveEnc.sensitiveEnc(tfBindQuickPay.getIdentityNo(), "identityno"));
						bindCardDO.setIdentityType(IdCardType.IC_IDCARD.getCode());
						bindCardDO.setIsMainCard(tfBindQuickPay.getPrimaryFlag());
						bindCardDO.setMobileNo(YHBFSensitiveEnc.sensitiveEnc(tfBindQuickPay.getMobileNo(),"mob"));
						bindCardDO.setModifyTime(new Date(tfBindQuickPay.getModifyTime()));
						//bindCardDO.setRealName(YHBFSensitiveEnc.sensitiveEnc(tfBindQuickPay.getRealName(), "realname"));
						bindCardDO.setRealName(tfBindQuickPay.getRealName());
						bindCardDO.setStatus(tfBindQuickPay.getStatus());    //未验证
						bindCardDO.setSwiftCode(tfBindQuickPay.getSwiftCode());
						bindCardDO.setUserId(userId);
						bindCardDO.setBindType(BindCardType.BIND_QUICK_PAY.getValue());
						bindCardDO.setCardType(tfBindQuickPay.getCardType());
						int cardActType = BanksManage.getcardActType(tfBindQuickPay.getSwiftCode(), tfBindQuickPay.getBankType().toString());
						if(cardActType == 2){
							LOG.error("当前卡为对公银行卡  不做迁移  tfBindQuickPay:"+JSONObject.toJSONString(tfBindQuickPay));
							continue;
						}
						bindCardDO.setCardActType(cardActType);
						
						
						Integer realBankType = tfBindQuickPay.getRealBankType();
						
						String bankId = BanksManage.getbankidBySwiftCode(tfBindQuickPay.getSwiftCode());
						if(bankId == null){
							LOG.error("该快捷支付卡暂时不支持,不做迁移   tfBindQuickPay: "+JSONObject.toJSONString(tfBindQuickPay));
							continue;
						}
						bindCardDO.setBankId(bankId);
						
						if (realBankType == 1 ) { //第三方支付渠道
							
						}else if (realBankType == 2 ) {//通付渠道
							bindCardDO.setChannelId(Constance.CHANNEL_ID_SZTF);
							bindCardDO.setChannelBindCardNo(tfBindQuickPay.getBindNo());
						}
						
						
						
						if (bindCardList == null) {
							bindCardList = new ArrayList<UserBindCardDO>();
						}
						
						
						
						
						//调用通付接口进行卡迁移
						if (realBankType == 2 ){
							BankCardBindingRpcService bankCardBindingRpcService = 
									dubboConsumerFactory.getDubboClient("bankCardBindingRpcService");
							ReqTransferBindOrder reqTransferBindOrder = new ReqTransferBindOrder();
							
							UserActDO payerUser = actService.findUserAct(userId, UserActType.SZTF);
							
							String channelActNo = userId;
							if (payerUser != null && payerUser.getChannelActNo() != null) {
								channelActNo = payerUser.getChannelActNo();
							}
							
							reqTransferBindOrder.setAccountId(channelActNo);
							reqTransferBindOrder.setCallbackUrl(null);
							reqTransferBindOrder.setChannelOrderId(tfBindQuickPay.getBindNo());
							reqTransferBindOrder.setOrderId(bindCardNo);
							reqTransferBindOrder.setUserId(userId);
							com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.ReqTransferBindOrder.BankCard bankCard = 
									new com.sztx.trade.payment.gateway.rpc.api.service.cardbinding.ReqTransferBindOrder.BankCard();
							bankCard.setBankCardNo(YHBFSensitiveEnc.sensitiveEnc(tfBindQuickPay.getBankCard(),"cardno"));
							bankCard.setCardType(tfBindQuickPay.getCardType());
							bankCard.setCvv(tfBindQuickPay.getCvv());
							bankCard.setExpireDate(tfBindQuickPay.getExpireDate());
							bankCard.setIdNo(YHBFSensitiveEnc.sensitiveEnc(tfBindQuickPay.getIdentityNo(), "identityno"));
							bankCard.setIdType(tfBindQuickPay.getIdentityType());
							bankCard.setPhone(YHBFSensitiveEnc.sensitiveEnc(tfBindQuickPay.getMobileNo(),"mob"));
							//bankCard.setRealName(YHBFSensitiveEnc.sensitiveEnc(tfBindQuickPay.getRealName(), "realname"));
							bankCard.setRealName(tfBindQuickPay.getRealName());
							reqTransferBindOrder.setBankCard(bankCard );
							try {
								bankCardBindingRpcService.transferBindOrder(reqTransferBindOrder);
								bindCardList.add(bindCardDO);
							} catch (Exception e) {
								LOG.error("快捷支付卡迁移失败",e);
							}
						}else{
							bindCardList.add(bindCardDO);
						}
					}
				}

				LOG.info("quickPayList:"+quickPayList);

				if (bindCardList != null) {
					userBindCardMysqlDAO.batchSave(bindCardList);
				}
			} else if ("110071005".equals(resultCode)) {
				return;
			} else {
				LOG.error("快捷支付卡迁移失败,"+rsp.getString("resultMsg"));
				throw new BusinessException(String.format("[%s]%s", resultCode, rsp.getString("resultMsg")));
			}
		} catch (Exception e) {
			LOG.error("快捷支付卡迁移失败",e);
			e.printStackTrace();
		}
	}
	
	
	
	private void transferWithdrawBankList(String userId, String channelId){
		
		LOG.info("开始同步用户{}在通付的提现绑卡信息", userId);
		
		MsgSrvProxyFacade msgSrvProxyFacade = dubboConsumerFactory.getDubboClient("msgSrvProxyFacade");
		
		JSONObject data = new JSONObject();
		data.put("userCode", userId);
		data.put("businessType", 1);    //业务编号:1-提现 2-转账到银行卡
		
		String connId = UUIDUtil.getNumUUID();
		
		String msg = MsgSrvUtil.createMessage("mobileInfoFacade", connId, "queryWithdrawCard", data.toJSONString());
		ProxyRequestParam param = new ProxyRequestParam(3, connId, 1, msg); // 3:新支付msgsrv，1:长连接
		String response = msgSrvProxyFacade.getResult(param);
		
		if (StringUtil.isBlank(response)) {			
			LOG.warn("Request user bind card list no response");
			return;
		}
		MsgSrvRsp rsp = new MsgSrvRsp(response);
		String resultCode = rsp.getString("resultCode");		
		try {
			if ("1001".equals(resultCode)) {
				byte[] d = Base64.decodeBase64(rsp.getString("data"));
				response = new String(d, "GBK");
				
				System.out.println(response);
				List<TfBindWithdraw> withdrawList = JSONObject.parseArray(response, TfBindWithdraw.class);	
				
				List<UserBindCardDO> bindCardList = null;
			
				if (withdrawList != null && !withdrawList.isEmpty()) {	
					List<UserBindCardDO> userBindCardDOs = queryBindCardList(userId, 2);
					for (TfBindWithdraw tfBindWithdraw : withdrawList) {							
						if (tfBindWithdraw.getState() == null || tfBindWithdraw.getState().intValue() != 1) {
							LOG.info("用户提现绑卡数据无效："+tfBindWithdraw);
							continue;
						}
						
						String tfBankCard = null;
						if (StringUtil.isNotBlank(tfBindWithdraw.getBankCard())){
							tfBankCard = YHBFUtil.decrypt(tfBindWithdraw.getBankCard());
						}else{
							LOG.error("卡号为空，无法进行迁移  ：tfBindWithdraw="+tfBindWithdraw);
							continue;
						}
						boolean flag = true;
						for (UserBindCardDO userBindCardDO : userBindCardDOs) {
							if(userBindCardDO.getCardNo().equals(tfBankCard)){
								LOG.error("该提现卡系统已经存在，无需迁移：tfBindWithdraw="+tfBindWithdraw);
								flag = false;
							}
						}
						if(flag == false){
							continue;
						}
						
						
						
						
						if (StringUtil.isNotBlank(tfBindWithdraw.getBankCard())) {
							tfBindWithdraw.setBankCard(YHBFUtil.decrypt(tfBindWithdraw.getBankCard()));
						}
						
						SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
						String bindCardNo = billnoService.nexBindCardNo();	
						
						UserBindCardDO bindCardDO = new UserBindCardDO();		
						bindCardDO.setBankName(tfBindWithdraw.getBankName());
//						bindCardDO.setBankType(bankType);
						bindCardDO.setBindCardNo(bindCardNo);
						bindCardDO.setCardActType(CardActType.CARD_ACT_PRIVATE.getValue());
//						bindCardDO.setCardCity(cardCity);
						bindCardDO.setCardNo(YHBFSensitiveEnc.sensitiveEnc(tfBindWithdraw.getBankCard(),"cardno"));
//						bindCardDO.setCardProvince(cardProvince);
//						bindCardDO.setCardCity(cardCity);
						bindCardDO.setCreateTime(sdf.parse(tfBindWithdraw.getCreateTime()));
//						bindCardDO.setExpireDate(tfBindWithdraw.getExpireDate());
//						bindCardDO.setIdentityNo(tfBindWithdraw.);
//						bindCardDO.setIdentityType(IdCardType.IC_IDCARD.getCode());
						bindCardDO.setIsMainCard(tfBindWithdraw.getPrimaryFlag());
//						bindCardDO.setMobileNo(tfBindWithdraw.getMobileNo());
						bindCardDO.setModifyTime(sdf.parse(tfBindWithdraw.getModifyTime()));
						//bindCardDO.setRealName(YHBFSensitiveEnc.sensitiveEnc(tfBindWithdraw.getCardUserName(), "realname"));
						bindCardDO.setRealName(tfBindWithdraw.getCardUserName());
						bindCardDO.setStatus(tfBindWithdraw.getState());    //未验证
						bindCardDO.setSwiftCode(tfBindWithdraw.getSwiftCode());
						bindCardDO.setUserId(userId);
						bindCardDO.setBindType(BindCardType.BIND_WITHDRAW.getValue());
						bindCardDO.setCardType(CardType.CARD_DEBIT.getValue());
						
						if (bindCardList == null) {
							bindCardList = new ArrayList<UserBindCardDO>();
						}						
						bindCardList.add(bindCardDO);
					}					
				}
				
				LOG.info("withdrawList:"+withdrawList);
				if (bindCardList != null) {
					userBindCardMysqlDAO.batchSave(bindCardList);
				}
			}
		}catch(Exception e){
			
		}
	}
	
	/**
	 * 查询通付账户余额
	 * 
	 * @param channelActNo 通付用户账号
	 * @return
	 * @author xiaosc
	 */
	private QueryUserActRespData queryTfBalance(String channelActNo){
		QueryUserActReqData  request = new QueryUserActReqData();
		request.setUserId(channelActNo);
		request.setRiskParams(getTfRiskParams());
		request.setMerId(Constance.SZTX_MER_ID);
		
		try {
			LOG.info("QueryUserAct request:"+JSONObject.toJSONString(request));
			QueryUserActRespData  req = sztfQueryService.queryUserAct(request);			
			LOG.info("QueryUserAct response:"+JSONObject.toJSONString(req));			
			if (req == null) {
				throw new BusinessException("查询账户余额失败");
			}			
			if (!Constance.PAY_SDK_SZTF_RESULT_SUCCESS.equals(req.getRspCode())) {
				throw new BusinessException(req.getRspMsg());
			}			
			return req;	
		} catch (Exception e) {
			LOG.error("通付用户账户信息查询失败", e);
			throw new BusinessException("交易系统服务繁忙，请稍后再试");
		}
	}
	
	
	/**
	 * 获取请求通付接口的风控参数
	 * 
	 * @return
	 * @author xiaosc
	 */
	private RiskParams getTfRiskParams(){
		
		RiskParams riskParams = new RiskParams();
		riskParams.setSrcChannel("10");
		riskParams.setProdAttrType("1");
		riskParams.setIp("127.0.0.1");
		return riskParams;
	}

	@Override
	public boolean unbindCard(String userId, String bindNo) {
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");
		ValidateUtil.isNotBlank(bindNo, "bindNo不能为空");
		
		UserBindCardDO bindCard = userBindCardMysqlDAO.findByIdAndUser(userId, bindNo);
		ValidateUtil.notNull(bindCard, "未找到用户["+userId+"]的绑定["+bindNo+"]信息");
		
		Integer status = bindCard.getStatus();
		
		if (status != null && (status.intValue() == BindCardStatus.UNAUTHORIZED.getValue() || status.intValue() == BindCardStatus.UNBIND.getValue())) {				
			return true;
		}
		
		UserBindCardDO updateBindCard = new UserBindCardDO();
		updateBindCard.setStatus(BindCardStatus.UNBIND.getValue());
		updateBindCard.setIsMainCard(0);
		
		userBindCardMysqlDAO.updateBindCard(updateBindCard , bindNo);
		
		return true;
	}

	@Override
	@Transactional
	public boolean setPrimaryCard(String userId, String bindNo) {
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");
		ValidateUtil.isNotBlank(bindNo, "bindNo不能为空");
		
		UserBindCardDO bindCard = userBindCardMysqlDAO.findByIdAndUser(userId, bindNo);
		ValidateUtil.notNull(bindCard, "未找到用户["+userId+"]的绑定["+bindNo+"]信息");
		
		int bindStatus = bindCard.getStatus();
		if (bindStatus != BindCardStatus.BIND.getValue()) {
			LOG.warn("该卡"+bindNo+"未绑定成功不允许设置主卡操作");
			return false;
		}
		
		int bindType = bindCard.getBindType();		
		if (bindType != BindCardType.BIND_QUICK_PAY.getValue() && bindType != BindCardType.BIND_WITHDRAW.getValue()) {			
			LOG.warn("绑定类别为["+bindType+"]不允许设置主卡操作");
			return false;
		}
		
		userBindCardMysqlDAO.unBindPrimaryCard(userId, bindType);	
		UserBindCardDO userBindCardDO = new UserBindCardDO();
		userBindCardDO.setIsMainCard(1);
		
		userBindCardMysqlDAO.updateBindCard(userBindCardDO , bindNo);
		return true;
	}

	@Override
	public List<UserBindCardDO> queryBindCardList(String userId, int bindType) {
		
//		List<BindInfo> resultList = null;
		
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");
//		ValidateUtil.isNotBlank(bindNo, "bindNo不能为空");
		BindCardType bType = BindCardType.valueOf(bindType);
//		if (bType == null) {
//			LOG.warn("bindType="+bindType+"传入有误");
//			return null;
//		}
		
		Integer type = bType == null ? null : bType.getValue();
		
		List<UserBindCardDO> listUserBindCardInfo = userBindCardMysqlDAO.listUserBindCardInfo(userId, type, BindCardStatus.BIND.getValue());
		
		//解密敏感数据
		bindCardDODec(listUserBindCardInfo);
	    return listUserBindCardInfo;

	}

	@Override
	public boolean verifyBindCard(String bindNo, String verifyCode) {
		
		ValidateUtil.isNotBlank(bindNo, "bindNo不能为空");
		ValidateUtil.isNotBlank(verifyCode, "verifyCode不能为空");
		
		UserBindCardDO bindCard = userBindCardMysqlDAO.findByUserCardNo(bindNo);
		if (bindCard == null) {
			throw new BusinessException("未找到"+bindNo+"绑定信息");			
		}
		
		int oldBindType = bindCard.getBindType();
		if (oldBindType != BindCardType.BIND_QUICK_PAY.getValue()) {
			throw new BusinessException("绑定卡"+bindNo+"非快捷支付绑卡，不处理");	
		}
		
		
		int oldStatus = bindCard.getStatus();		
		if (oldStatus == BindCardStatus.BIND.getValue()) { //已绑定成功  
			LOG.info("该绑定号"+bindNo+"已绑定成功过");
			return true;
		}
		
		
		BankCardBindingRpcService bankCardBindingRpcService = dubboConsumerFactory.getDubboClient("bankCardBindingRpcService");
		ReqVerifyBindBankCard req = new ReqVerifyBindBankCard();
		req.setOrderId(bindNo);
		req.setVerifyCode(verifyCode);
		
		RespVerifyBindBankCard  resp = bankCardBindingRpcService.verifyBindBankCard(req);
		
		if (resp == null) {
			LOG.error("请求网关验证绑卡信息无响应");
			throw new BusinessException("系统异常，请稍后再试！");
		}
		
		return handBindQuickPayCardResult(resp);
	}
	
	
	public boolean handBindQuickPayCardResult(RespVerifyBindBankCard  resp){
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setName("com.sztx.pay.center.core.service.impl.AccountServiceImpl.handBindQuickPayCardResult");
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);	
		TransactionStatus tranStatus = txManager.getTransaction(def);
		
		String bindCardNo = resp.getOrderId();	
		String bankId = resp.getBankId();
		String channelBindNo = resp.getChannelBindNo();
		String payChannelId = resp.getChannelId();
//		Integer recharged = resp.getMoneyRecharged();
		String resultCode = resp.getResultCode();
		String resultMsg = resp.getResultMsg();
		
		BindCardStatus status = BindCardStatus.UNAUTHORIZED;
		UserBindCardDO updateBind = new UserBindCardDO();
		updateBind.setModifyTime(new Date());
		updateBind.setInnerRemark(resultMsg);
		
		if (RespVerifyBindBankCard.RC_OK.equals(resultCode)) {//返回成功
			status = BindCardStatus.BIND;
			updateBind.setBankId(bankId);
			updateBind.setPayChannelId(payChannelId);
			updateBind.setChannelBindCardNo(channelBindNo);
		}else if (RespVerifyBindBankCard.RC_REQ_INVALID.equals(resultCode)) {  //请求参数错误
			status = BindCardStatus.BIND_FAILED;
		}else if (RespVerifyBindBankCard.RC_UNKNOWN.equals(resultCode)) {//结果未知
			
		}else if (RespVerifyBindBankCard.RC_VERIFY_CODE_INCORRECT.equals(resultCode)) { //验证码输入错误，需重新输入 
			
		}else if (RespVerifyBindBankCard.RC_FAILED.equals(resultCode)) {//验证码输入错误，不能重新验证
			status = BindCardStatus.BIND_FAILED;	
		}else{
			throw new BusinessException("交易系统服务繁忙，请稍后再试");
		}
		
		
		
		
		try {
			
			UserBindCardDO bindCard = userBindCardMysqlDAO.findByUserCardNoLock(bindCardNo);
			//解密敏感数据
			bindCardDODec(bindCard);
			if (bindCard == null) {
				LOG.error("未找到绑定卡"+bindCardNo+"相关信息");
				return false;
			}
			
			int oldBindType = bindCard.getBindType();
			if (oldBindType != BindCardType.BIND_QUICK_PAY.getValue()) {
				LOG.error("绑定卡"+bindCardNo+"非快捷支付绑卡，不处理");
				return false;	
			}
			
			int oldStatus = bindCard.getStatus();		
			if (oldStatus == BindCardStatus.BIND.getValue()) { //已绑定成功  
				LOG.info("该绑定号"+bindCardNo+"已绑定成功过");
				return true;
			}
			
			updateBind.setStatus(status.getValue());
			
			//未绑定该银行卡  才允许更新状态
			if(checkBindedCard(bindCard.getCardNo(), bindCard.getUserId())){
				userBindCardMysqlDAO.updateBindCard(updateBind, bindCardNo);	
			}
			
			if (status == BindCardStatus.BIND) { //绑卡成功		
				String userId = bindCard.getUserId();
				String realName = bindCard.getRealName();
				String identityNo = bindCard.getIdentityNo();
				String mobileNo = bindCard.getMobileNo();
				
				UserInfoDO userInfo = userInfoService.findUserInfo(userId);
				if (userInfo.getIsRealName() == 0) {				
					userInfoService.realName(userId, identityNo, realName, mobileNo, "admin", "绑卡实名");
					notifyUserCenterRealInfo(userId, realName, identityNo);
				}
				
				
				//通知缴费       告知已经完成了绑卡实名认证
				
				BindCardMqMsg bindCardMqMsg = new BindCardMqMsg();
				bindCardMqMsg.setBankId(bankId);
				bindCardMqMsg.setBankName(bindCard.getBankName());
				bindCardMqMsg.setBindCardNo(bindCardNo);
				bindCardMqMsg.setBindType(bindCard.getBindType());
				bindCardMqMsg.setCardActType(bindCard.getCardActType());
				bindCardMqMsg.setCardNo(bindCard.getCardNo());
				bindCardMqMsg.setCardType(bindCard.getCardType());
				bindCardMqMsg.setIdentityNo(identityNo);
				bindCardMqMsg.setIdentityType(bindCard.getIdentityType());
				bindCardMqMsg.setMobileNo(mobileNo);
				bindCardMqMsg.setRealName(realName);
				bindCardMqMsg.setUserId(userId);
				
				String routingKey = "pay.center.bindcard";
				if (StringUtil.isNotBlank(bindCard.getChannelId())) {
					routingKey += "."+bindCard.getChannelId();
				}
				
				mqMessageService.sendBindCardMsg(bindCardMqMsg,routingKey);
				
				LOG.info("绑卡成功通知缴费---bindCardNo:{}, routingKey:{}, bindCardMqMsg:{}",bindCardNo,routingKey,JSONObject.toJSONString(bindCardMqMsg));
				
				
				
				
				Integer isWithdrawCard = bindCard.getIsWithdrawCard();
				if (isWithdrawCard != null && isWithdrawCard.intValue() == 1) {
					
					CardActType cardActType = CardActType.valueOf(bindCard.getCardActType());
					CardType cardType = CardType.valueOf(bindCard.getCardType());
					
					//对私借记卡才允许绑定提现卡
					if ((cardActType != null && cardActType == CardActType.CARD_ACT_PRIVATE ) && (cardType != null && cardType == CardType.CARD_DEBIT)) {
						String updateUser = "admin";
						String cardNo = YHBFSensitiveEnc.sensitiveDec(bindCard.getCardNo(),"cardno");
						String cardProvince = null;
						String cardCity = null;
						String bankAddr = null;
						String autoRemark = null;
						String companyName = null;
						String bankName = bindCard.getBankName();
						String swiftCode = bindCard.getSwiftCode();
						
						bindWithdraw(userId, cardActType , cardNo , realName, mobileNo, cardProvince , cardCity , cardType , bankAddr , autoRemark , companyName , identityNo, updateUser , bankName , swiftCode );
					}
				}
				
			}
			//绑卡走的支付接口   会自动结算到账户   不需要再进行加款
//			if (recharged != null) {
//				int value = recharged.intValue();			
//				if (value >0) {  //快捷支付绑卡扣取								
//					UserActType userActType = UserActType.CASH;				
//					String channelId = bindCard.getChannelId();				
//					if (JFUtils.isJFChannel(channelId)) {
//						userActType = UserActType.JF;
//					}
//					
//					bindCardRecharge(bindCardNo, recharged, bindCard.getUserId(), userActType);
//				}else if (value < 0) {
//					LOG.error("绑定快捷支付的费用不能小于0，moneyRecharged="+value);
//					throw new BusinessException("交易系统服务繁忙，请稍后再试");
//				}
//			}	

		} catch (Exception ex) {
			txManager.rollback(tranStatus);
			LOG.error("处理绑卡结果出错", ex);
			throw new BusinessException(ex);
		}finally{				
			if (!tranStatus.isCompleted()) {
				txManager.commit(tranStatus);
			}
		}
		
		if (RespVerifyBindBankCard.RC_VERIFY_CODE_INCORRECT.equals(resultCode)) {
			throw new BusinessException("绑卡验证码输入错误，请重新输入");
		}else if (RespVerifyBindBankCard.RC_FAILED.equals(resultCode)) {//验证码输入错误，不能重新验证
			throw new BusinessException(resultMsg);
		}

		return true;
	}
	
	private boolean checkBindedCard(String cardNo,String userId){
		cardNo = YHBFSensitiveEnc.sensitiveEnc(cardNo, "cardno");
		List<UserBindCardDO> userBindCardDOList = userBindCardMysqlDAO.findByCardNoLock(userId,Constance.BindCardType.BIND_QUICK_PAY.getValue(), cardNo);
		if(userBindCardDOList != null){
			for (UserBindCardDO userBindCardDO : userBindCardDOList) {
				if(userBindCardDO.getStatus() == 1){
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * <一句话功能简述>
	 * <功能详细描述>
	 * @param userId
	 * @param realName
	 * @param identifyNo
	 * @author xiaosc
	 * @date 2016年3月23日 下午7:21:35 
	 * @see [类、类#方法、类#成员]
	 */
	private void notifyUserCenterRealInfo(String userId, String realName, String identifyNo){//通知用户系统实名认证
		//TODO
		
		JSONObject jObject = new JSONObject();
		jObject.put("userCode", userId);
		jObject.put("realName", realName);
		jObject.put("identifyNo", identifyNo);
		
		mqMessageService.sendCommentMsg(jObject.toJSONString());
	}
	
	private void bindCardRecharge(String bindCardNo, int recharged, String userId, UserActType userActType){
		
		UserActDO userActDO = actService.findUserAct(userId, userActType);
		if (userActDO == null) {
			LOG.error("");
			return;
		}
		
		if (userActDO.getActState() == ActState.CANCELLATION.getCode()) {
			LOG.error("");
			return;
		}
		
		UserInfoDO uInfo = userInfoService.findUserInfo(userId);
		if (uInfo == null) {
			LOG.error("");
			return;
		}
		
		PayCoreTransferReq req = new PayCoreTransferReq();
		req.setAmount(recharged);
		req.setAttach("绑卡充值");
		req.setFeeAmount(0l);
		req.setOrderId(bindCardNo);
		req.setOriginOrderId(bindCardNo);
		req.setTradeOrderType(TradeOrderType.BIND_CARD_ORDER);
		req.setPayerUserId(Constance.USER_SZTX);
		req.setPayerUserType(Constance.UserType.SZTX.getCode());
		req.setPayerActNo(Constance.ACT_SZTX);
		req.setPayerActType(UserActType.CASH);
		
		req.setPayeeUserId(userActDO.getUserId());
		req.setPayeeUserType(uInfo.getUserType());
		req.setPayeeActNo(userActDO.getActNo());
		req.setPayeeActType(userActType);
		req.setBusinessType("1022");//设置业务类型为1022
		try {
			payCoreService.balanceTransfer(req );
			TradeFlowMessage message = new TradeFlowMessage();
			
			message.setTradeType(TradeMessageType.CHARGE.getCode());
			message.setBerbonAcc(userActDO.getUserId());
			message.setBusinessType("1022");
			message.setTradeAmount(recharged);
			message.setReceiveAmount(recharged);
			message.setTradeOrderNo(bindCardNo);
			UserBindCardDO userBindCardDO = findUserBindInfo(bindCardNo, userActDO.getUserId(), BindCardType.BIND_QUICK_PAY);
			String cardNo = YHBFSensitiveEnc.sensitiveDec(userBindCardDO.getCardNo(), "cardno");
			cardNo = cardNo.substring(cardNo.length() - 4, cardNo.length());
			String payType = userBindCardDO.getBankName() + "(" + cardNo + ")";
			message.setPayType(payType);
			LOG.info("绑卡mq通知trade-center:" + bindCardNo);
			sendTradeFlowMessage(message );
		} catch (Exception e) {
			LOG.error("用户"+userId+"绑卡时，充值出错", e);
		}
		
		
	}
	private boolean sendTradeFlowMessage(TradeFlowMessage message) {
		String json = JSONObject.toJSONString(message);
		mqMessageService.sendTradeFlowMsg(json);
		return true;
	}
//	private void bindCardRecharge(String bindCardNo, String userId, Integer value){
//		UserActDO userAct = findBalanceActInfo(userId);
//		
//		if (userAct == null) {
//			LOG.error("绑卡充值时，未找到"+userId+"相关的账户信息");	
//		}			
//					//TODO 将绑卡的金额转账到用户的余额账户
//		LOG.info("快捷支付绑卡扣取费用:" + value);	
//					
//		PayCoreTransfer payCoreTransfer = new PayCoreTransfer();
//		payCoreTransfer.setPayerUserId(Constance.USER_ID_SZTX);
//		payCoreTransfer.setPayerUserType(UserType.SZTX);
//		payCoreTransfer.setPayerAccountId(Constance.ACT_SZTX_CASH);
////		payCoreTransfer.setPayerActType(null);
//		payCoreTransfer.setPayerTfActNo(Constance.ACT_SZTX_CASH);
//					
//		payCoreTransfer.setPayeeUserId(userAct.getUserId());
//		payCoreTransfer.setPayeeUserType(UserType.valueOf(userAct.getUserType()));
//		payCoreTransfer.setPayeeAccountId(userAct.getActNo());
//		payCoreTransfer.setPayeeTfActNo(userAct.getChannelActNo());
//		payCoreTransfer.setPayeeActType(ActType.valueOf(userAct.getActType()));					
//		payCoreTransfer.setAmount(value);
//		payCoreTransfer.setAttach("绑卡充值");
//		payCoreTransfer.setInnerTransferType(InnerTransferType.B2C);
//					
//		payCoreTransfer.setReferOrderId(bindCardNo);
//		payCoreTransfer.setTradeOrderType(TradeOrderType.BIND_CARD_ORDER);
//					
//		payCoreService.transfer(payCoreTransfer , null,bindCardNo);
//		//TODO  需要记录用户账户流水
//		
//		
//		
//	}

	@Override
	public boolean changeUserType(String userId, Integer userType,
			String attach) {
			
		ValidateUtil.isNotBlank(userId, "用户berbonId不能为空");
		List<UserType> userTypeList = UserType.listOf(userType);
		ValidateUtil.notNull(userTypeList, "userType参数有误");
		
		
		if (StringUtil.isNotBlank(attach)) {
			ValidateUtil.strMaxLen(attach, 255, "attach超过255个字符");
		}
		
		UserInfoDO userInfo = userInfoService.findUserInfo(userId);
		
		if (userInfo == null) {			
			throw new BusinessException("未找到该用户"+userId);
		}
		
		Integer isRealName = userInfo.getIsRealName();
		if (isRealName == null || isRealName.intValue() != 1) { //用户未实名
			UserVO userVo = getUserInfo(userId);				
			if (userVo == null) {
				LOG.warn("用户{}在用户中心未找到", userId);
				throw new BusinessException("用户"+userId+"不存在");
			}
			
			String realName = userVo.getRealname();
			String identityNo = userVo.getIdentityid();
			String mobileNo = userVo.getMob();
			
			if (StringUtil.isBlank(realName)) {
				LOG.info("用户{}真实姓名{}为空", userId, realName);
				realName = null;
			}
			
			if (!IDCardUtil.isIDCard(identityNo)) {
				LOG.info("用户{}身份证号{}有误", userId, identityNo);
				identityNo = null;
			}
			
			if (realName != null && identityNo != null) {					
				if (StringUtil.isNotBlank(mobileNo)) {
					try {
						ValidateUtil.isMobile(mobileNo, "");
					} catch (Exception e) {
						mobileNo = null;
						LOG.warn("用户{}手机号{}格式不正确", userId, mobileNo);
					}
				}
				
				userInfoService.realName(userId, identityNo, realName, mobileNo, "admin", null);
			}
		}
			
		int actState = userInfo.getUserStatus(); 			
		ValidateUtil.isNotTrue(actState == 0, "用户["+userId+"]账户已存在处于冻结中");			
		
		int oldUserType = userInfo.getUserType();
		List<UserType> oldUserTypeList = UserType.listOf(oldUserType);
		
		List<UserType> subList = (List<UserType>) CollectionUtils.subtract(userTypeList, oldUserTypeList);
		if (subList != null && !subList.isEmpty()) {
			UserInfoDO newUserInfo = new UserInfoDO();
			newUserInfo.setUserType(userType);
			newUserInfo.setRemark(attach);
			userInfoService.updateUserInfo(userId, newUserInfo );			
		}
		
		actService.createUserAct(userId, userType);
		
		return true;
	}

	@Override
	public boolean resendVerifyCode(String bindNo) {
		ValidateUtil.isNotBlank(bindNo, "bindNo不能为空");
		
		UserBindCardDO bindCard = userBindCardMysqlDAO.findByUserCardNo(bindNo);
		if (bindCard == null) {
			throw new BusinessException("未找到"+bindNo+"绑定信息");			
		}
		
		int oldBindType = bindCard.getBindType();
		if (oldBindType != BindCardType.BIND_QUICK_PAY.getValue()) {
			throw new BusinessException("绑定卡"+bindNo+"非快捷支付绑卡，不处理");	
		}
		
		
		int oldStatus = bindCard.getStatus();		
		if (oldStatus == BindCardStatus.BIND.getValue()) { //已绑定成功  
			LOG.info("该绑定号"+bindNo+"已绑定成功过");
			return true;
		}
		
		BankCardBindingRpcService bankCardBindingRpcService = dubboConsumerFactory.getDubboClient("bankCardBindingRpcService");
		ReqReSendVerifyCode req = new ReqReSendVerifyCode();
		req.setOrderId(bindNo);
		
		RespReSendVerifyCode reSendVerifyCode = bankCardBindingRpcService.reSendVerifyCode(req);
		
		if ("1".equals(reSendVerifyCode.getResultCode())) {
			throw new BusinessException(reSendVerifyCode.getResultMsg());
		} 
		
		return true;
	}

	@Override
	public UserBindCardDO findUserBindInfo(String bindNo) {
		UserBindCardDO cardInfo = userBindCardMysqlDAO.findByUserCardNo(bindNo);
		if (cardInfo == null ) {
			throw new BusinessException("用户绑定号["+bindNo+"]不存在");
		}
		//0未认证，1已认证, 2已解绑
		int status = cardInfo.getStatus();
		if (status == 0) {			
			throw new BusinessException("用户["+cardInfo.getUserId()+"]绑定号["+bindNo+"]未认证");
		}else if (status == 2) {
			throw new BusinessException("用户["+cardInfo.getUserId()+"]绑定号["+bindNo+"]已解绑");
		}
		bindCardDODec(cardInfo);
		return cardInfo;
	}

	@Override
	public UserBindCardDO findLastBindCardInfo(String userId) {
		UserBindCardDO bindCardDo = userBindCardMysqlDAO.lastUserBindCardInfo(userId, BindCardType.BIND_QUICK_PAY.getValue(), BindCardStatus.BIND.getValue());
		bindCardDODec(bindCardDo);
		return bindCardDo;
	}

	@Override
	public UserBindCardDO findLastWithdrawCardInfo(String userId) {
		String bindCardNo = orderWithdrawMysqlDAO.findLastWithdrawBindNo(userId);
		UserBindCardDO bindCardDo = userBindCardMysqlDAO.findByBindCardNo(userId, BindCardType.BIND_WITHDRAW.getValue(), bindCardNo);
		bindCardDODec(bindCardDo);
		return bindCardDo;
	}

	@Override
	public UserBindCardDO findLastChargeCardInfo(String userId) {
		String bindCardNo = orderRechargeMysqlDAO.getLastChargeBindNo(userId);
		UserBindCardDO bindCardDo = userBindCardMysqlDAO.findByBindCardNo(userId, BindCardType.BIND_QUICK_PAY.getValue(), bindCardNo);
		bindCardDODec(bindCardDo);
		return bindCardDo;
	}

	@Override
	public Integer findLastChannelId(String userId) {
		OrderB2cDO orderB2cDO = orderB2cMysqlDAO.findLastOrderByUserId(userId);
		String payBankId = orderB2cDO.getPayBankId();
		if(StringUtil.isBlank(payBankId)){
			return null;
		}
		String startW = payBankId.substring(0, 1);
		return Integer.parseInt(startW);
	}
	
	private void bindCardDODec(UserBindCardDO bindCardDO){
		if(bindCardDO == null){
			return;
		}
		String cardNo = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getCardNo(),"cardno");
		//String realName = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getRealName(), "realname");
		String realName = bindCardDO.getRealName();
		String identityNo = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getIdentityNo(), "identityno");
		String mobileNo = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getMobileNo(),"mob");
		bindCardDO.setCardNo(cardNo);
		bindCardDO.setRealName(realName);
		bindCardDO.setIdentityNo(identityNo);
		bindCardDO.setMobileNo(mobileNo);
	}
	private void bindCardDODec(List<UserBindCardDO> bindCardDOs){
		if(bindCardDOs == null || bindCardDOs.size() < 1){
			return;
		}
		for (UserBindCardDO bindCardDO : bindCardDOs) {
			String cardNo = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getCardNo(),"cardno");
			//String realName = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getRealName(), "realname");
			String realName = bindCardDO.getRealName();
			String identityNo = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getIdentityNo(), "identityno");
			String mobileNo = YHBFSensitiveEnc.sensitiveDec(bindCardDO.getMobileNo(),"mob");
			bindCardDO.setCardNo(cardNo);
			bindCardDO.setRealName(realName);
			bindCardDO.setIdentityNo(identityNo);
			bindCardDO.setMobileNo(mobileNo);
		}
	}

	@Override
	public UserActInfoResponse queryMchAct(String partner,String actType) {
		return null;
	}

	@Override
	public UserActInfoResponse queryUserAct(String actNo,String actType,String userId) {
		ValidateUtil.isNotBlank(actNo, "用户actNo不能为空");
		UserActType userActType = UserActType.valueOf(actType);
		ValidateUtil.notNull(userActType, "用户actNo不能为空");
		
		UserActInfoResponse response = new UserActInfoResponse();
		
		
		QueryUserActReqData  request = new QueryUserActReqData();
		request.setUserId(actNo);
		request.setRiskParams(getTfRiskParams());
		request.setMerId(Constance.SZTX_MER_ID);
		
		int tfActStatus = 1;
		try {
			LOG.info("QueryUserAct request:"+JSONObject.toJSONString(request));
			QueryUserActRespData  req = sztfQueryService.queryUserAct(request);			
			LOG.info("QueryUserAct response:"+JSONObject.toJSONString(req));
			response.setBalance(req.getBalance());
			response.setFreezedBalance(req.getFreezedBalance());
			if(req.getActStatus() != null){
				if(req.getActStatus().equals("OK")){
					tfActStatus = ActState.NORMAL.getCode();
				}else if(req.getActStatus().equals("FREEZED")){
					tfActStatus = ActState.STOP_PAY.getCode();
				}else if(req.getActStatus().equals("CLOSED")){
					tfActStatus = ActState.CANCELLATION.getCode();
				}
			}
		} catch (Exception e) {
			LOG.error("通付用户账户信息查询失败", e);
			throw new BusinessException("交易系统服务繁忙，请稍后再试");
		}
				
		UserVO userVO = getUserInfo(userId);
		if(userVO != null){
			String nickName = userVO.getNickName();
			String realname = userVO.getRealname();
			response.setNickName(nickName);
			response.setRealName(realname);
		}
		
		
//		QueryPayUserInfoService queryPayUserInfoService = dubboConsumerFactory.getDubboClient("queryPayUserInfoService");
//		UserBaseInfoVO userBaseInfo = queryPayUserInfoService.getUser(userId);
//		if(userBaseInfo != null){
//			response.setRealName(userBaseInfo.getRealName());
//		}
		
		
		UserActDO user = actService.findUserAct(userId, userActType);
		if (user != null) {	//账户已存且账户状态正将直接将账户返回		
			int actState = user.getActState(); 
			response.setActStatus(actState);
			
			response.setUserType(user.getUserType());
			response.setCreateTime(user.getCreateTime());
			response.setModifyTime(user.getCreateTime());
			
		}else{
			response.setActStatus(tfActStatus);
		}
		response.setUserId(userId);
		return response;
	}

	@Override
	public UserStatusInfoVO queryUserStatusInfo(String userId) {
		QueryUserInfoService queryUserInfoService = dubboConsumerFactory.getDubboClient("queryUserInfoService");
		return queryUserInfoService.getUserStatusInfo(userId);
	}

	public ResponsePageModel<UserBindCardDO> queryMchCardList(QueryMerBindCardRequest request) {
		ResponsePageModel<UserBindCardDO> response = new ResponsePageModel<UserBindCardDO>();
		ValidateUtil.ge(request.getPageNo(), 0, "pageNo错误");
		ValidateUtil.ge(request.getPageSize(), 1, "pageSize错误");
		String startTime = null;
		String endTime = null;
		if(request.getStartTime() != null){
			startTime = DateUtil.formatDate(request.getStartTime(), DateUtil.LONG_DATE_FORMAT_STR);
		}
		if(request.getEndTime() != null){
			endTime = DateUtil.formatDate(request.getEndTime(), DateUtil.LONG_DATE_FORMAT_STR);
		}
		int counts = userBindCardMysqlDAO.countMchBindCard(request.getUserId(), request.getStatus(), startTime, endTime, request.getCompanyName());
		response.setTotal(counts);
		if(counts > 0){
			PageQuery pageQuery = new PageQuery(request.getPageNo(), request.getPageSize());
			List<UserBindCardDO> listUserBindCardInfo = userBindCardMysqlDAO.listMchBindCardInfo(request.getUserId(), pageQuery, request.getStatus(), startTime, endTime, request.getCompanyName());
			//解密敏感数据
			bindCardDODec(listUserBindCardInfo);
			response.setResultLists(listUserBindCardInfo);
		}
	    return response;
	}

	@Override
	public void updateMchBindInfo(String userId, String bindCardNo,
			BindInfo bindInfo) {
		ValidateUtil.isNotBlank(userId, "userId不能为空");
		ValidateUtil.isNotBlank(bindCardNo, "bindNo不能为空");
		ValidateUtil.notNull(bindInfo, "bindInfo不能为空");
		
		String cardNo = bindInfo.getCardNo();
		String realName = bindInfo.getRealName();
		String identityNo = bindInfo.getIdentityNo();
		String mobileNo = bindInfo.getMobileNo();
		String cardProvince = bindInfo.getCardProvince();
		String cardCity = bindInfo.getCardCity();
		String bankAddr = bindInfo.getBankAddr();
		String autoRemark = bindInfo.getAutoRemark();
		String companyName = bindInfo.getCompanyName();
		String updateUser = bindInfo.getUpdateUser();
		Integer status = bindInfo.getStatus();
		
		String bankName = bindInfo.getBankName();
		String swiftCode = bindInfo.getSwiftCode();
		Date mDate = new Date();
		
		
		UserBindCardDO bindCardDO = new UserBindCardDO();	
		bindCardDO.setBindType(BindCardType.BIND_WITHDRAW.getValue());
		bindCardDO.setBankName(bankName);
		bindCardDO.setBindCardNo(bindCardNo);
		bindCardDO.setCardActType(2);
		bindCardDO.setIdentityType(IdCardType.IC_IDCARD.getCode());
		bindCardDO.setIsMainCard(0);
		bindCardDO.setModifyTime(mDate);
		bindCardDO.setStatus(1);    //提现卡默认验证通过
		bindCardDO.setSwiftCode(swiftCode);
		bindCardDO.setUserId(userId);
		bindCardDO.setCardType(1);
		if(identityNo != null)
			bindCardDO.setIdentityNo(identityNo);
		if(cardNo != null)
			bindCardDO.setCardNo(cardNo);
		if(cardProvince != null)
			bindCardDO.setCardProvince(cardProvince);
		if(cardCity != null)
			bindCardDO.setCardCity(cardCity);
		if(mobileNo != null)
			bindCardDO.setMobileNo(mobileNo);
		if(realName != null)
			bindCardDO.setRealName(realName);
		if(bankAddr != null)
			bindCardDO.setBankAddr(bankAddr);
		if(autoRemark != null)
			bindCardDO.setAutoRemark(autoRemark);
		if(companyName != null)
			bindCardDO.setCompanyName(companyName);
		if(updateUser != null)
			bindCardDO.setOperator(updateUser);
		if(status != null){
			bindCardDO.setStatus(status);
		}else{
			bindCardDO.setStatus(1);
		}
			
		userBindCardMysqlDAO.updateBindCard(bindCardDO, bindCardNo);
	}

	@Override
	public void callPayResult(PayCoreTradeInfo tradeInfo) {
		/***添加绑卡回调 start***/
		String mappingOrderId = tradeInfo.getReferOrderId();
		//映射表反查订单
		String tradeOrderId = orderMappingService.getTradeOrderId(mappingOrderId);
		if(StringUtils.isNoneBlank(tradeOrderId) && tradeOrderId.startsWith(Constance.BIND_CARD_START_WITH)){
			//为绑卡   交易订单
			RespVerifyBindBankCard verifyResult = new RespVerifyBindBankCard();
			verifyResult.setChannelBindNo(null);
			verifyResult.setBankId(tradeInfo.getChannelBankId());
			verifyResult.setChannelId(tradeInfo.getChannelId());
			verifyResult.setMoneyRecharged((int)tradeInfo.getAmount());
			verifyResult.setOrderId(tradeOrderId);
			PayFlowState payFlowState = tradeInfo.getPayFlowState();
			String resultCode;
			switch (payFlowState) {
			case SUCCESS:
				resultCode = RespVerifyBindBankCard.RC_OK;
				break;
			case FAIL:
				resultCode = RespVerifyBindBankCard.RC_FAILED;		
				break;
			case EXCEPTION:
				resultCode = RespVerifyBindBankCard.RC_UNKNOWN;
				break;
			default:
				resultCode = RespVerifyBindBankCard.RC_UNKNOWN;
				break;
			}
			verifyResult.setResultCode(resultCode);
			verifyResult.setResultMsg(tradeInfo.getPayFlowDesc());
			handBindQuickPayCardResult(verifyResult);
			return;
		}
		/***添加绑卡回调 end***/
		
		
		
		
		
		
		
		
		if (tradeInfo == null) {
			LOG.error("tradeInfo为空不处理");
			return;
		}
		
		String referId = tradeInfo.getReferOrderId();
		if (StringUtil.isBlank(referId)) {
			LOG.error("referId为空不处理");
			return;
		}
		
		if (!referId.startsWith(Constance.ORDER_PREFIX_BALANCE_TRANSFER)) {//账户迁移单
			LOG.error("非迁移订单不处理");
			return;
		}
		
		
		PayFlowState state = tradeInfo.getPayFlowState();
		if (state == null || state != PayFlowState.SUCCESS) {
			LOG.warn("账户转款不成不处理");
			return;
		}

		long tradeAmount = tradeInfo.getAmount();	
		String userId = tradeInfo.getPayerUserId();
		int userType = tradeInfo.getPayerUserType();
		
		UserInfoDO uInfo = userInfoService.findUserInfo(userId);
		if (uInfo == null) {
			LOG.warn("未找到迁移用户"+userId+"");
		}
		
		UserActType userActType = UserActType.CASH;
		boolean isJf = (uInfo.getUserType() & UserType.AGENT.getCode()) != 0;		
		if (isJf) {
			userActType = UserActType.JF;
		}
		
		UserActDO userAct = actService.findUserAct(userId, userActType );
		if (userAct == null) {
			LOG.warn("未找到迁移用户"+userId+"的"+userActType.getDesc());
			return ;
		}
		
		if (userAct.getActState() == ActState.CANCELLATION.getCode()) {
			LOG.warn("迁移用户"+userId+"的"+userActType.getDesc()+userAct.getActNo()+"已注销");
			return ;
		}
		
		boolean flag = lockRedisDAO.lockOrder(referId, PayFlowState.SUCCESS.getCode()+"", "grayorder", 60*60*24*30);
		if (!flag) {	
			LOG.warn("灰度用户余额迁移订单{}已处理", referId);
			return;
		}
				
		PayCoreTransferReq req = new PayCoreTransferReq();
		req.setAmount(tradeAmount);
		req.setAttach("余额迁移");
		req.setFeeAmount(0l);
		req.setOrderId(referId);
		req.setOriginOrderId(referId);
		req.setTradeOrderType(TradeOrderType.BALANCE_TRANSFER);
		req.setPayerUserId(Constance.USER_SZTX);
		req.setPayerUserType(Constance.UserType.SZTX.getCode());
		req.setPayerActNo(Constance.ACT_SZTX);
		req.setPayerActType(UserActType.CASH);
		
		req.setPayeeUserId(userId);
		req.setPayeeUserType(userType);
		req.setPayeeActNo(userAct.getActNo());
		req.setPayeeActType(userActType);
		
		try {
			payCoreService.balanceTransfer(req );
		} catch (Exception e) {
			LOG.error("用户"+userId+"绑卡时，充值出错", e);
		}
		
		UserInfoDO newUserInfo = new UserInfoDO();
		newUserInfo.setGrayState(1);
		
		userInfoService.updateUserInfo(userId, newUserInfo );
	}

	@Override
	public boolean freezedBalance(String userId, Integer actType,
			String operator, String attach) {
		UserActType uType = UserActType.valueOf(actType);
		
		ValidateUtil.notNull(uType, "actType传入有误");
		
		UserActDO userAct =	actService.findUserAct(userId, uType);
		
		ValidateUtil.notNull(userAct, "用户"+userAct+uType.getDesc()+"不存在");
		
		actService.freezeAct(userAct.getActNo(), operator, attach);
		
		return true;
	}

	@Override
	public boolean unfreezeBalance(String userId, Integer actType,
			String operator, String attach) {
		UserActType uType = UserActType.valueOf(actType);
		
		ValidateUtil.notNull(uType, "actType传入有误");
		
		UserActDO userAct =	actService.findUserAct(userId, uType);
		
		ValidateUtil.notNull(userAct, "用户"+userAct+uType.getDesc()+"不存在");
		
		actService.unfreezeAct(userAct.getActNo(), operator, attach);
		
		return true;
	}

	
	@Override
	public boolean freezeMoney(String userId, Integer actType, long amount,
			String operator, String attach) {
		
		UserActType uType = UserActType.valueOf(actType);
		
		ValidateUtil.notNull(uType, "actType传入有误");
		
		UserActDO userAct =	actService.findUserAct(userId, uType);
		
		ValidateUtil.notNull(userAct, "用户"+userAct+uType.getDesc()+"不存在");
		
		String originOrderNo = null;		
		String payFlowId = userId + "" + System.currentTimeMillis();		
		Date payTime = new Date();		
		TradeOrderType tradeType = TradeOrderType.FREEZE_MONEY;		
		String businessType = null;
		
		actService.freezeMoney(userAct.getActNo(), amount, originOrderNo , payFlowId, payTime , tradeType , attach, operator, businessType );
		
		return true;
	}

	@Override
	public boolean unfreezeMoney(String userId, Integer actType, long amount,
			String operator, String attach) {
		
		UserActType uType = UserActType.valueOf(actType);
		
		ValidateUtil.notNull(uType, "actType传入有误");
		
		UserActDO userAct =	actService.findUserAct(userId, uType);
		
		ValidateUtil.notNull(userAct, "用户"+userAct+uType.getDesc()+"不存在");
		
		String originOrderNo = null;		
		String payFlowId = userId + "" + System.currentTimeMillis();		
		Date payTime = new Date();		
		TradeOrderType tradeType = TradeOrderType.UNFREEZE_MONEY;		
		String businessType = null;
		
		actService.unfreezeMoney(userAct.getActNo(), amount, originOrderNo , payFlowId, payTime , tradeType , attach, operator, businessType );
		return true;
	}
	
	
	private void notifyUserCenterPayAct(String userId){
		try {
			String url = ConfigUtil.getTransferUserNotifyUrl();
			url = String.format(url, userId, userId);
			LOG.info("mangeToNew url:"+url);
			HttpClientUtil.get(url);
		} catch (Exception e) {
			LOG.info("用户迁移通知新用户中心异常,userId:"+userId,e);
		}
		
		
	}
	
	
	
	
	class SyncBindCardInfo implements Runnable{
		private String userId;
		private Integer userType;
		private String msgno;

		public SyncBindCardInfo(String userId, Integer userType, String msgno) {
			super();
			this.userId = userId;
			this.userType = userType;
			this.msgno = msgno;
		}

		@Override
		public void run() {
			try {
				LogMsgNoConverter.setMsgno(msgno);
				if (userId == null || userType == null) {
					return;
				}
				
				String channelId = "10";				
				if ((UserType.AGENT.getCode() & userType) != 0) { //用户有缴费角色
					channelId = "99";
				}
				
				transferBindCard(userId, channelId);
				transferWithdrawBankList(userId, channelId);
			} catch (Exception e) {
				LOG.error("", e);
			}finally{
				LogMsgNoConverter.clear();
			}
		}	
	}


	@Override
	public boolean isGrayUser(String userId) {
		
		return userRedisDAO.isGrayUser(userId);
	}

	@Override
	public boolean syncUserBalance(String userId) {
		ValidateUtil.isNotBlank(userId, "userId不能为空");
		
		UserActDO tfActInfo = actService.findUserAct(userId, UserActType.SZTF);
		UserInfoDO userInfo = userInfoService.findUserInfo(userId);
		
		if (userInfo == null ) {				
			throw new BusinessException("用户"+userId+"未灰度到新系统，不能同步用户余额");
		}
		
		if (tfActInfo == null) {
			throw new BusinessException("未找到用户"+userId+"在通户的余额账户，不能同步用户余额");
		}
		
		Integer userType = userInfo.getUserType();		
		String tfActNo = tfActInfo.getChannelActNo();

		try {
			tranferUserBalance(userId, userType , tfActNo);
		} catch (Exception e) {
			LOG.info("同步用户"+userId+"在通付账户"+tfActNo+"失败", e);
		}
		
		if (!userId.equals(tfActNo)) {
			LOG.info("同步用户{}在通付余额", userId, userId);					

			tfActInfo = actService.findUserAct(userId, UserActType.TFAC);
			if (tfActInfo == null) {
				//判断用户在能通付的账户是否有迁移
				String realName = userInfo.getRealName();
				String identityNo = userInfo.getIdentityNo();
				String mobileNo = userInfo.getMobile();
				
				if (StringUtil.isBlank(realName) || StringUtil.isBlank(identityNo)) {				
					LOG.info("用户{}的真实姓名{},身份证号{},不同步余额", realName, identityNo);
					return false;
				}
							
			    //通付账户不存在，先迁移通付账户
				MigrateUserRespData resp = tfTransfer(userId, true, mobileNo, realName, identityNo);
				tfActNo = resp.getUserId();
							
				LOG.info("用户{}在通付的账户{}不存在,创建通付账户", userId, tfActNo);
				tfActInfo = createSztfAct(userId, tfActNo, "灰度用户迁移", UserActType.TFAC.getCode());	
			}
			
			tranferUserBalance(userId, userType , userId);
		}
		
		return true;
	}

	@Override
	public boolean realNameTfAct(String userId, String realName,
			String identityNo, String mobileNo) {
		
		ValidateUtil.isNotBlank(userId, "userId不存在");	
		UserVO userVO = getUserInfo(userId);
		
		if (userVO == null ) {
			throw new BusinessException("用户不存在");
		}

		if (StringUtil.isBlank(realName)) {
			throw new BusinessException("真实姓名不能为空");
		}
		
		if (!IDCardUtil.isIDCard(identityNo)) {
			throw new BusinessException("身份证不合法");
		}
		
		if (StringUtil.isNotBlank(mobileNo)) {			
			ValidateUtil.isMobile(mobileNo, "手机号不合法");
		}
		
		String tfActNo = null;
		UserActDO tfActInfo = actService.findUserAct(userId, UserActType.SZTF);
		if (tfActInfo == null) {			
			MigrateUserRespData resp = tfTransfer(userId, true, mobileNo, realName, identityNo);
			tfActNo = resp.getUserId();
		}else {
			
			tfActNo = tfActInfo.getChannelActNo();
			if (StringUtil.isBlank(tfActNo)) {
				tfActNo = userId;
			}
			QueryUserActRespData tfUserAct = queryTfBalance(tfActNo);
			
			String userGrade = tfUserAct.getUserGrade();
			
			LOG.info("用户{}，用户在通付的等级为{}", userId, userGrade);
			
			if (StringUtil.isBlank(userGrade) || !StringUtil.isNumeric(userGrade)) {
				LOG.info("用户在通付的用户等级为{},不能处理", userGrade);
				throw new BusinessException("用户"+userId+"在通付实名等级有误");
			}
			
			int grade = Integer.parseInt(userGrade);
			if (grade >= 2) {				
				return true;				
			}
			
			realSztfAuth(userId, realName, identityNo, mobileNo, tfActNo);
			
			notifyUserCenterRealInfo(userId, realName, identityNo);
			
			
			return true;
		}
		
		return false;
	}

	@Override
	public boolean changeGrayState(String userId, Integer newGraySate) {
		
		ValidateUtil.isNotBlank(userId, "userId不能为空");
		ValidateUtil.notNull(newGraySate, "newGraySate不能为空");
		if (newGraySate.intValue() != 0 && newGraySate.intValue() != 1) {
			throw new BusinessException("newGraySate="+newGraySate+"参数错误");
		}
		
		UserInfoDO newUserInfo = new UserInfoDO();
		newUserInfo.setGrayState(newGraySate);
		
		userInfoService.updateUserInfo(userId, newUserInfo );
		return true;
	}

	@Override
	public boolean syncBindCard(String userId) {		
		UserInfoDO userInfo = userInfoService.findUserInfo(userId);
		
		if (userInfo == null ) {				
			throw new BusinessException("用户"+userId+"未灰度到新系统，不能同步用户卡信息");
		}		
		taskExecutor.execute(new SyncBindCardInfo(userId, userInfo.getUserType(), LogMsgNoConverter.getCurrentMsgno()));		
		
		return true;
	}

	@Override
	public List<UserInfoResponse> queryUserActList(UserInfoRequest request,
			int pageNo, int pageSize) {
		UserInfoDO userInfoDO = new UserInfoDO();
		BeanUtils.copyProperties(request, userInfoDO);
		
		PageQuery pageQuery = new PageQuery(pageNo, pageSize);
		List<UserInfoListDO> userInfoList = userInfoMysqlDAO.findUserAccountList(userInfoDO, pageQuery );
		List<UserInfoResponse> responseList = new ArrayList<UserInfoResponse>();
		for (UserInfoListDO userInfoListDO : userInfoList) {
			UserInfoResponse tmpUserInfoResponse = new UserInfoResponse();
			BeanUtils.copyProperties(userInfoListDO, tmpUserInfoResponse);
			List<UserActDetail> userActDetail = new ArrayList<UserActDetail>();
			List<UserActDO> userActDOS = userInfoListDO.getUserActDOS();
			for (UserActDO userActDO : userActDOS) {
				UserActDetail detail = new UserInfoResponse().new UserActDetail();
				BeanUtils.copyProperties(userActDO, detail);
				userActDetail.add(detail);
			}
			tmpUserInfoResponse.setUserActDetail(userActDetail);
			
			UserStatusInfoVO userStatusInfoVO = queryUserStatusInfo(tmpUserInfoResponse.getUserId());
			if(userStatusInfoVO != null){
				tmpUserInfoResponse.setLoginPwdState(userStatusInfoVO.getLoginPwdState());
				tmpUserInfoResponse.setPayPwdState(userStatusInfoVO.getPayPwdState());
			}
			
			
			responseList.add(tmpUserInfoResponse);
		}
		
		return responseList;
	}

	@Override
	public Integer queryUserActCount(UserInfoRequest request) {
		UserInfoDO userInfoDO = new UserInfoDO();
		BeanUtils.copyProperties(request, userInfoDO);
		return userInfoMysqlDAO.findUserAccountCount(userInfoDO);
	}

	@Override
	public List<UserActAmountDO> queryUserAmountCollect(List<String> includeUsers){
		return userActMysqlDAO.queryUserAmountCollect(includeUsers);
	}
	@Override
	public int queryCollectAmountUserCount(List<String> includeUsers){
		return userInfoMysqlDAO.queryCollectAmountUserCount(includeUsers);
	}
	
	
}
